From: Gavin Carr Date: Sun, 2 Dec 2007 22:19:26 +0000 (+0000) Subject: Add initial microformat plugins. X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;h=2c18c54630ee453b3074c153a92438ebdec8e726;p=matthijs%2Fupstream%2Fblosxom-plugins.git Add initial microformat plugins. --- diff --git a/gavinc/hcard b/gavinc/hcard new file mode 100644 index 0000000..b02dfc1 --- /dev/null +++ b/gavinc/hcard @@ -0,0 +1,143 @@ +# Blosxom Plugin: hcard +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc hcard' +# Requires: metaclear, metamail, uf_hcard_meta + +package hcard; + +use strict; +use IO::File; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configuration defaults ----- + +my %config = ( + + # Where is the hcard metadata? + hcard_meta_file => "$blosxom::datadir/hcard.yml", + +); + +# -------------------------------- + +use vars qw($hcard); +$hcard = ''; + +sub start { + # Check $hcard_meta_file exists + unless (-f $config{hcard_meta_file}) { + warn "(hcard) cannot find hcard_meta_file file '$config{hcard_meta_file}' - aborting\n"; + return 0; + } + return 1; +} + +sub skip { + my $hcard_fh = IO::File->new( $config{hcard_meta_file}, 'r' ) + or warn "(hcard) cannot open hcard_meta_file file '$config{hcard_meta_file}': $! - aborting\n" + and return 0; + my @hcard_data = <$hcard_fh>; + my $hcard_title = $hcard_data[0]; + chomp $hcard_title; + my $hcard_body = join '', @hcard_data[ 1 .. $#hcard_data ]; + $hcard_fh->close; + # debug(1, "hcard_body: $hcard_body"); + + unless ($hcard_body) { + warn "(hcard) no data found in hcard_meta_file file '$config{hcard_meta_file}' - aborting\n"; + return 0; + } + + # Fake story calls to metaclear, metamail and uf_hcard_meta to render the hcard + my @story_args = ( undef, undef, undef, undef, \$hcard_title, \$hcard_body ); + metaclear::story( @story_args ); + metamail::story( @story_args ); + uf_hcard_meta::story( @story_args ); + + $hcard = $uf_hcard_meta::hcard; + + return 0; +} + +1; + +__END__ + +=head1 NAME + +hcard - blosxom plugin to set a global $hcard::hcard variable for use in templates + +=head1 DESCRIPTION + +L is a blosxom plugin to set a global $hcard::hcard variable for use in +templates. It is intended to allow you to set up a global hcard for yourself +to be displayed somewhere in your blog template. + +To use, simply define the set of hcard data you want to use in the 'hcard_meta_file' +file ($blosxom::datadir/hcard.yml, by default). + +=head1 EXAMPLES + +Here's an example hcard.yml for me: + + Name: Gavin Carr + Organisation: Open Fusion + Role: Chief Geek + Email: gavin@openfusion.com.au + URL: http://www.openfusion.net/ + Suburb: Wahroonga + State: NSW + Postcode: 2076 + Country: Australia + Latitude: -33.717718 + Longitude: 151.117158 + HCard-Class: nodisplay + HCard-Style: div-span + +=head1 USAGE + +L requires the L, L, and L plugins, +but has no particular ordering requirements with respect to them. + +=head1 SEE ALSO + +L, L, L. + +Microformats.org: http://www.microformats.org/, http://microformats.org/wiki/hcard. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl:sw=4 diff --git a/gavinc/uf_adr_meta b/gavinc/uf_adr_meta new file mode 100644 index 0000000..dd9f18d --- /dev/null +++ b/gavinc/uf_adr_meta @@ -0,0 +1,218 @@ +# Blosxom Plugin: uf_adr_meta +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc uf_adr_meta' + +package uf_adr_meta; + +use strict; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configuration defaults ----- + +my %config = ( + + # Extra CSS classes to add to the microformat container e.g. to turn display off + class => '', + #class => 'nodisplay', + + # Whether to automatically add microformat to story bodies. If not set, + # you must explicitly add $uf_adr_meta::adr to a template somewhere. + auto_append_to_body => 1, + + # What markup style to use for your adr, if auto-appending. + # 3 styles are currently defined: + # 'div-span' uses a 'div' elt for the container, and 'span' elements for the fields + # 'ul' uses a 'ul' list for the container, and 'li' elements for the fields + # 'dl' uses a 'dl' list for the container, 'dt' elements for field names, and + # 'dd' elements for the fields themselves + #style => 'div-span', + #style => 'ul', + style => 'dl', + +); + +# -------------------------------- + +use vars qw($adr); + +# Official adr attributes +my @attr = qw(post-office-box extended-address street-address + locality region postal-code country-name); +# Attribute aliases +my %alias = ( + 'post-office-box' => 'pobox', + 'street-address' => 'street', + locality => 'city', + region => 'state', + 'postal-code' => 'postcode', + 'country-name' => 'country', +); +# Attributes which if set will cause us to skip this plugin (looks like an hcard) +my @skip_attr = qw(fn name); + +$config{style} = 'div-span' unless $config{style} eq 'ul' or $config{style} eq 'dl'; + +sub start { 1 } + +# Return the first existing metadata item key and value given a list of keys +sub _get_meta { + for my $attr ( @_ ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr}; + $value = eval "\$meta::$attr" unless defined $value; + return wantarray ? ( $attr, $value ) : $value if defined $value; + } + return wantarray ? () : undef; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + # Skip if any of the @skip_attr are set + for (@skip_attr) { + return 1 if $blosxom::meta{$_} || eval "\$meta::$_"; + } + + my $story_style = _get_meta( 'adr_style' ) || $config{style}; + my $ctag = $story_style eq 'div-span' ? 'div' : $story_style; + my $etag = $story_style eq 'div-span' ? 'span' : + $story_style eq 'ul' ? 'li' : 'dd'; + + $adr = ''; + for my $attr ( @attr ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr} || eval "\$meta::$attr" + || $blosxom::meta{ $alias{$attr} } || eval "\$meta::$alias{$attr}"; + next unless defined $value; + $adr .= qq(
$attr
) if $story_style eq 'dl'; + $adr .= qq(<$etag class="$attr">$value\n); + } + if ($adr) { + my $container_classes = 'adr'; + if (my $meta_class = _get_meta('adr_class')) { + $container_classes .= " $meta_class"; + } + else { + $container_classes .= " $config{class}" if $config{class}; + } + $adr = qq(<$ctag class="$container_classes">\n$adr\n); + # debug(1, "uf_adr_meta: $adr\n"); + } + + my $autoappend = _get_meta( 'adr_autoappend' ); + $autoappend = $config{auto_append_to_body} unless defined $autoappend; + return 1 unless $autoappend; + + $$body_ref .= "\n\n$adr\n\n"; + + return 1; +} + +1; + +__END__ + +=head1 NAME + +uf_adr_meta - plugin to create an 'adr' microformat tag from post +metadata + +=head1 DESCRIPTION + +uf_adr_meta is a plugin to create an 'adr' microformat tag from metadata +in your post. The microformat tag is created in the $uf_adr_meta::adr +variable for use in templates or by other plugins, or if the +'auto_append_to_body' config variable is set (it is by default), +uf_adr_meta will append the tag to your story body automatically. + +=head2 OPTIONAL METADATA ITEMS + +=over 4 + +=item post-office-box (alt: pobox) + +=item extended-address + +=item street-address (alt: street) + +=item locality (alt: city) + +=item region (alt: state) + +=item country-name (alt: country) + +=back + +=head2 Config Elements + +uf_adr_meta also supports a couple of config elements that can be used to +override plugin config data on a per-story basis: + +=over 4 + +=item Adr-Class (metamail) / adr_class (meta) + +This class (or list of classes) is appended to the class list applied to the +top-level adr element in the rendered adr i.e. it overrides the +'class' config variable. + +=item Adr-Autoappend (metamail) / adr_autoappend (meta) + +This is a flag (0 or 1) indicating whether the rendered adr should be +automatically appended to the story body. It overrides the 'auto_append_to_body' +config variable. + +=item Adr-Style (metamail) / adr_style (meta) + +One of the following styles: 'div-span', 'ul', 'dl', used to render the adr. +It overrides the 'style' config variable. + +=back + +=head1 USAGE + +uf_adr_meta should be loaded after the meta plugins (meta +itself, or the metaclear/metamail/metadir/metafile family). + +=head1 SEE ALSO + +Microformats.org: http://www.microformats.org/, http://microformats.org/wiki/address. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl diff --git a/gavinc/uf_geo_meta b/gavinc/uf_geo_meta new file mode 100644 index 0000000..fbb06c7 --- /dev/null +++ b/gavinc/uf_geo_meta @@ -0,0 +1,221 @@ +# Blosxom Plugin: uf_geo_meta +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc uf_geo_meta' + +package uf_geo_meta; + +use strict; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configurable variables ----- + +my %config = ( + + # Extra CSS classes to add to the microformat container e.g. to turn display off + class => '', + #class => 'nodisplay', + + # Whether to automatically add microformat to story bodies. If not set, + # you must explicitly add $uf_adr_meta::adr to a template somewhere. + auto_append_to_body => 1, + + # What markup style to use for your adr, if auto-appending. + # 3 styles are currently defined: + # 'div-span' uses a 'div' elt for the container, and 'span' elements for the fields + # 'ul' uses a 'ul' list for the container, and 'li' elements for the fields + # 'dl' uses a 'dl' list for the container, 'dt' elements for field names, and + # 'dd' elements for the fields themselves + #style => 'div-span', + #style => 'ul', + style => 'dl', + +); + +# -------------------------------- + +use vars qw($geo); + +# Attributes which if set will cause us to skip this plugin (looks like an adr) +my @skip_attr = qw(locality region postal-code country-name city state postcode country); + +$config{style} = 'div-span' unless $config{style} eq 'ul' or $config{style} eq 'dl'; + +sub start { 1 } + +# Return the first existing metadata item key and value given a list of keys +sub _get_meta { + for my $attr ( @_ ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr}; + $value = eval "\$meta::$attr" unless defined $value; + return wantarray ? ( $attr, $value ) : $value if defined $value; + } + return wantarray ? () : undef; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + # Skip if any of the @skip_attr are set + for (@skip_attr) { + return 1 if $blosxom::meta{$_} || eval "\$meta::$_"; + } + + my $story_style = _get_meta( 'geo_style' ) || $config{style}; + my $ctag = $story_style eq 'div-span' ? 'div' : $story_style; + my $etag = $story_style eq 'div-span' ? 'span' : + $story_style eq 'ul' ? 'li' : 'dd'; + my $sep = ', ' if $story_style eq 'div-span'; + + my $latitude = _get_meta('latitude'); + my $longitude = _get_meta('longitude'); + return 1 unless defined $latitude && defined $longitude; + + $geo = ''; + my $container_classes = 'geo'; + if (my $meta_class = _get_meta('geo_class')) { + $container_classes .= " $meta_class"; + } + else { + $container_classes .= " $config{class}" if $config{class}; + } + + $geo .= qq(<$ctag class="$container_classes">); + $geo .= qq(
Latitude
) if $story_style eq 'dl'; + $geo .= qq(<$etag class="latitude">$latitude); + $geo .= $sep if $story_style = 'div-span'; + $geo .= qq(
Longitude
) if $story_style eq 'dl'; + $geo .= qq(<$etag class="longitude">$longitude); + $geo .= qq(); + # debug(1, "uf_geo_meta: $geo\n"); + + my $autoappend = _get_meta( 'geo_autoappend' ); + $autoappend = $config{auto_append_to_body} unless defined $autoappend; + return 1 unless $autoappend; + + $$body_ref .= "\n\n$geo\n\n"; + + return 1; +} + +1; + +__END__ + +=head1 NAME + +uf_geo_meta - plugin to create a 'geo' microformat tag from post metadata + +=head1 DESCRIPTION + +uf_geo_meta is a plugin to create a 'geo' microformat tag from metadata +in your post. The microformat tag is created in the $uf_geo_meta::geo +variable for use in templates or by other plugins, or if the +'auto_append_to_body' config variable is set (it is by default), uf_geo_meta +will append the tag to your story body automatically. + +=head2 REQUIRED METADATA ITEMS + +=over 4 + +=item latitude + +A decimal between -90.0 (South Pole) and +90.0 (North Pole), indicating +degrees of latitude. + +=item longitude + +A decimal between -180.0 (western hemisphere) and +180.0 (eastern hemisphere), +indicating degrees of longitude. + +=back + +If any required metadata is missing the plugin just skips the story. + +=head2 Config Elements + +uf_geo_meta also supports a couple of config elements that can be used to +override plugin config data on a per-story basis: + +=over 4 + +=item Geo-Class (metamail) / geo_class (meta) + +This class (or list of classes) is appended to the class list applied to the +top-level geo element in the rendered geo i.e. it overrides the +'class' config variable. + +=item Geo-Autoappend (metamail) / geo_autoappend (meta) + +This is a flag (0 or 1) indicating whether the rendered geo should be +automatically appended to the story body. It overrides the 'auto_append_to_body' +config variable. + +=item Geo-Style (metamail) / geo_style (meta) + +One of the following styles: 'div-span', 'ul', 'dl', used to render the geo. +It overrides the 'style' config variable. + +=back + +=head1 EXAMPLE + +Adding a geo microformat to your post then becomes as simple as: + + Testing uf_geo_meta + Latitude: -33.717770 + Longitude: 151.115886 + +if using metamail, or: + + Random blog post + meta-latitude: -33.717770 + meta-longitude: 151.115886 + +=head1 USAGE + +uf_geo_meta should be loaded after the meta plugins (meta +itself, or the metaclear/metamail/metadir/metafile family). + +=head1 SEE ALSO + +Microformats.org: http://www.microformats.org/, +http://microformats.org/wiki/geo. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl diff --git a/gavinc/uf_hcalendar_meta b/gavinc/uf_hcalendar_meta new file mode 100644 index 0000000..9cfa760 --- /dev/null +++ b/gavinc/uf_hcalendar_meta @@ -0,0 +1,353 @@ +# Blosxom Plugin: uf_hcalendar_meta +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc uf_hcalendar_meta' + +package uf_hcalendar_meta; + +use strict; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configurable variables ----- + +my %config = ( + + # Extra CSS classes to add to the microformat container e.g. to turn display off + class => '', + #class => 'nodisplay', + + # Whether to automatically add microformat to story bodies. If not set, + # you must explicitly add $uf_adr_meta::adr to a template somewhere. + auto_append_to_body => 1, + + # What markup style to use for your adr, if auto-appending. + # 3 styles are currently defined: + # 'div-span' uses a 'div' elt for the container, and 'span' elements for the fields + # 'ul' uses a 'ul' list for the container, and 'li' elements for the fields + # 'dl' uses a 'dl' list for the container, 'dt' elements for field names, and + # 'dd' elements for the fields themselves + #style => 'div-span', + #style => 'ul', + style => 'dl', + +); + +# -------------------------------- + +use vars qw($hcalendar); + +my @required = qw(summary dtstart); +my @optional = qw(dtend duration description location url uid); +my %label = ( + dtstart => 'DtStart', + dtend => 'DtEnd', + uid => 'UID', + url => 'URL', +); + +$config{style} = 'div-span' unless $config{style} eq 'ul' or $config{style} eq 'dl'; + +sub start { 1 } + +# Return the first existing metadata item key and value given a list of keys +sub _get_meta { + for my $attr ( @_ ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr}; + $value = eval "\$meta::$attr" unless defined $value; + return wantarray ? ( $attr, $value ) : $value if defined $value; + } + return wantarray ? () : undef; +} + +sub _format_date { + my ($date) = @_; + my $iso_date = $date; + $iso_date =~ s/^(\d{4}-\d{2}-\d{2})(\s+)/$1T/; + return $iso_date; +} + +sub _format_duration { + my ($duration) = @_; + my $iso_duration = uc $duration; + + # Trim + $iso_duration =~ s/^\s+//; + $iso_duration =~ s/\s+$//; + + # If $iso_duration begins with an H, M, or S element, and no P, insert PT + $iso_duration =~ s/^(\d+)([HMS])/PT$1$2/; + + # Otherwise, if $iso_duration begins without a P, insert one + $iso_duration =~ s/^(\d)/P$1/; + + # Replace date-time whitespace with 'T' + $iso_duration =~ s/([PYMD])\s+/$1T/; + + return $iso_duration; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + my %meta = (); + for (@required, @optional) { + $meta{$_} = _get_meta($_); + } + my @req_count = map { $meta{$_} ? 1 : () } @required; + return 1 unless @req_count == @required; + + my $story_style = _get_meta( 'hcal_style' ) || $config{style}; + my $ctag = $story_style eq 'div-span' ? 'div' : $story_style; + my $etag = $story_style eq 'div-span' ? 'span' : + $story_style eq 'ul' ? 'li' : 'dd'; + + $hcalendar = ''; + my $container_classes = 'vevent'; + if (my $meta_class = _get_meta('hcal_class')) { + $container_classes .= " $meta_class"; + } + else { + $container_classes .= " $config{class}" if $config{class}; + } + $hcalendar .= qq(<$ctag class="$container_classes">\n); + for (@required, @optional) { + next unless defined $meta{$_}; + $hcalendar .= sprintf qq(
%s
), $label{$_} || ucfirst $_ + if $story_style eq 'dl'; + if ($_ eq 'dtstart' || $_ eq 'dtend') { + my $iso_date = _format_date($meta{$_}); + $hcalendar .= qq(<$etag>$meta{$_}\n); + } + elsif ($_ eq 'duration') { + my $iso_duration = _format_duration($meta{$_}); + $hcalendar .= qq(<$etag>$meta{$_}\n); + } + elsif ($_ eq 'url') { + $hcalendar .= qq(<$etag>$meta{url}\n); + } + else { + $hcalendar .= qq(<$etag class="$_">$meta{$_}\n); + } + } + $hcalendar .= qq(\n); + # debug(1, "uf_hcalendar_meta: $hcalendar\n"); + + my $autoappend = _get_meta( 'hcal_autoappend' ); + $autoappend = $config{auto_append_to_body} unless defined $autoappend; + return 1 unless $autoappend; + + $$body_ref .= "\n\n$hcalendar\n\n"; + + return 1; +} + +1; + +__END__ + +=head1 NAME + +uf_hcalendar_meta - plugin to create an 'hcalendar' microformat tag from +post metadata + +=head1 DESCRIPTION + +uf_hcalendar_meta is a plugin to create an 'hcalendar' microformat tag +from metadata in your post. The microformat tag is created in the +$uf_hcalendar_meta::hcalendar variable for use in templates or by other +plugins, or if the $auto_append_to_body flag is set (it is by default), +uf_hcalendar_meta will append the tag to your story body automatically. + +=head2 REQUIRED METADATA ITEMS + +(If using the 'metamail/metadir/metafile' plugins, metadata items +are matched case insensitively.) + +=over 4 + +=item summary + +The summary or title of the event. + +=item dtstart + +The start date/time of the event. + +Must be given as an ISO 8601 calendar date, in the form +YYYY-MM-DDTHH:MM:SS or YYYYMMDDTHHMMSS, with an optional trailing +timezone of the form /[+-]HH(:?MM)?/. Any number of rightmost time +elements may be omitted. Hours must be given in 24-hour time. + +For convenience, this plugin allows the 'T' marker to be replaced by +whitespace. + +The following are all valid dtstart values, for example: + +=over 4 + +=item 2007-09-01T19:30:00+10:00 + +=item 20070901T193000-10 + +=item 2007-09-01 + +=item 2007-09-01 17:45 + +=back + +=back + +And one of: + +=over 4 + +=item dtend + +The end date/time of the event. Must be an ISO 8601 calendar date +as defined for dtstart above. + +=item duration + +The duration of the event. This may be an ISO 8601 duration, of the +form PnnYnnMnnDTnnHnnMnnS e.g. "P3Y6M4DT12H30M0S". Elements may be +omitted if their duration is zero. The smallest value used may also +have a decimal fraction, as in "P0.5Y" to indicate half a year. + +For convenience, this plugin interprets the units case-insensitively, +allows the 'P' and 'T' markers to be omitted, and also accepts +whitespace in the place of the 'T' time marker. + +Note that because months and minutes use the same signifier, there is +ambiguity about the meaning of 'P1M' and '1M'. This plugin interprets +'M' values as follows: + +=over 4 + +=item 1M + +Interpreted as minutes, since this is the most common use case, and +since ISO 8601 really requires a leading 'P' signifier. + +=item P1M + +Interpreted as months, following ISO 8601. + +=item PT1M + +Interpreted as minutes, following ISO 8601. + +=back + +=back + + +=head2 OPTIONAL METADATA ITEMS + +=over 4 + +=item description + +A description of the event, sometimes longer than the summary. + +=item dtend + +The end date/time of the event, as discussed above. + +=item duration + +The duration of the event, as discussed above. + +=item location + +A string describing the location of the event. + +=item url + +A canonical URL for the event. + +=item uid + +A unique identifier for this event. Apparently required by some +versions of Microsoft Outlook. + +=back + +=head2 Config Elements + +uf_hcalendar_meta also supports a couple of config elements that can be used to +override plugin config data on a per-story basis: + +=over 4 + +=item HCal-Class (metamail) / hcal_class (meta) + +This class (or list of classes) is appended to the class list applied to the +top-level hcalendar element in the rendered hcalendar i.e. it overrides the +'class' config variable. + +=item HCal-Autoappend (metamail) / hcal_autoappend (meta) + +This is a flag (0 or 1) indicating whether the rendered hcalendar should be +automatically appended to the story body. It overrides the 'auto_append_to_body' +config variable. + +=item HCal-Style (metamail) / hcal_style (meta) + +One of the following styles: 'div-span', 'ul', 'dl', used to render the hcalendar. +It overrides the 'style' config variable. + +=back + +=head1 USAGE + +uf_hcalendar_meta should be loaded after the meta plugins (meta +itself, or the metaclear/metamail/metadir/metafile family). + +=head1 SEE ALSO + +Microformats.org: http://www.microformats.org/, +http://microformats.org/wiki/hcalendar. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 BUGS + +Only the most common hcalendar attributes have been implemented +so far. Please let me know if you'd like something not available +yet. + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl diff --git a/gavinc/uf_hcard_meta b/gavinc/uf_hcard_meta new file mode 100644 index 0000000..55efc3b --- /dev/null +++ b/gavinc/uf_hcard_meta @@ -0,0 +1,449 @@ +# Blosxom Plugin: uf_hcard_meta +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc uf_hcard_meta' + +package uf_hcard_meta; + +use strict; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 2; + +# --- Configuration defaults ----- + +my %config = ( + + # Extra CSS classes to add to the microformat container e.g. to turn display off + class => '', + #class => 'nodisplay', + + # Whether to automatically add microformat to story bodies. If not set, + # you must explicitly add $uf_adr_meta::adr to a template somewhere. + auto_append_to_body => 1, + + # What markup style to use for your adr, if auto-appending. + # 3 styles are currently defined: + # 'div-span' uses a 'div' elt for the container, and 'span' elements for the fields + # 'ul' uses a 'ul' list for the container, and 'li' elements for the fields + # 'dl' uses a 'dl' list for the container, 'dt' elements for field names, and + # 'dd' elements for the fields themselves + #style => 'div-span', + #style => 'ul', + style => 'dl', + +); + +# -------------------------------- + +use vars qw($hcard); + +# Official hcard attributes +my @req_attr = qw(fn); +my %opt_attr = ( + 'adr' => [ qw(address-type post-office-box extended-address street-address + locality region postal-code country-name) ], + 'agent' => 1, + 'bday' => 1, + 'email' => 1, + 'geo' => [ qw(latitude longitude) ], + 'key' => 1, + 'label' => 1, + 'logo' => 1, + 'mailer' => 1, + 'n' => [ qw(honorific-prefix given-name additional-name family-name honorific-suffix) ], + 'nickname' => 1, + 'note' => 1, + 'org' => [ qw(organization-name organization-unit) ], + 'photo' => 1, + 'rev' => 1, + 'role' => 1, + 'sort-string' => 1, + 'sound' => 1, + 'tel' => 1, + 'tz' => 1, + 'uid' => 1, + 'url' => 1, +); + +# Attribute aliases +my %alias = ( + 'fn' => [ 'name' ], + 'email-value' => [ 'email' ], + 'tel' => [ qw(telephone phone) ], + 'organization-name' => [ qw(org organisation organization) ], + 'post-office-box' => [ 'pobox' ], + 'street-address' => [ 'street' ], + 'locality' => [ 'suburb', 'city' ], + 'region' => [ 'state' ], + 'postal-code' => [ 'postcode' ], + 'country-name' => [ 'country' ], +); +my %attr_types = map { $_ => 1 } qw(tel); +my %attr_types_standalone = ( + tel => { map { $_ => 1 } qw(fax cell mobile) }, +); +my %alias_types = ( + mobile => 'cell', +); + +$config{style} = 'div-span' unless $config{style} eq 'ul' or $config{style} eq 'dl'; + +sub start { 1 } + +# Return the first existing metadata item key and value given a list of keys +sub _get_meta { + for my $attr ( @_ ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr}; + $value = eval "\$meta::$attr" unless defined $value; + return wantarray ? ( $attr, $value ) : $value if defined $value; + } + return wantarray ? () : undef; +} + +sub _add_attr { + my ($hcard, $attr, $value, $style, $parent_attr, $parent_started, $type) = @_; + + # Start parent if set and not started + if ($parent_attr && (! defined $parent_started || ! $$parent_started)) { + $$hcard .= qq(\n); + $$parent_started = 1 if defined $parent_started; + } + + # Append hcard output + my $label = ''; + if ($type) { + $label = join ', ', map { qq($_) } split /[_\W]+/, $type; + } + elsif ($attr =~ m/^(\w+)-(value)$/) { + $label = $1; + $attr = $2; + } + elsif ($style eq 'dl') { + $label = $attr; + $label =~ s/\s+/-/g; + } + my $type_string; + if ($style eq 'dl') { + $$hcard .= qq(
$label
); + $type_string = ''; + } + elsif ($label) { + $type_string = "($label) "; + } + my $etag = $style eq 'div-span' ? 'span' : + $style eq 'ul' ? 'li' : 'dd'; + $$hcard .= qq(<$etag class="$attr">$type_string$value\n); + + # Close parent unless we have a $parent_started flag to set + $$hcard .= qq(
\n) if $parent_attr && ! defined $parent_started; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + # Skip unless all required attributes are set + for (@req_attr) { + my $value = _get_meta($_, $alias{$_} ? @{$alias{$_}} : ()); + unless ($value) { + # debug(2, "No name attribute found in $path/$filename - skipping post"); + return 1; + } + } + + my $story_style = _get_meta( 'hcard_style' ) || $config{style}; + my $ctag = $story_style eq 'div-span' ? 'div' : $story_style; + + $hcard = ''; + my $container_classes = 'vcard'; + if (my $meta_class = _get_meta('hcard_class')) { + $container_classes .= " $meta_class"; + } + else { + $container_classes .= " $config{class}" if $config{class}; + } + $hcard .= qq(<$ctag class="$container_classes">\n); + for my $attr ( @req_attr ) { + my $value = _get_meta( $attr, $alias{$attr} ? @{$alias{$attr}} : () ); + _add_attr(\$hcard, $attr, $value, $story_style) if $value; + } + for my $attr ( sort keys %opt_attr ) { + # Allow nested attributes + if (ref $opt_attr{$attr}) { + my $parent_attr = $attr; + my $parent_started = 0; + for $attr ( @{ $opt_attr{$parent_attr} } ) { + my $value = _get_meta( $attr, $alias{$attr} ? @{$alias{$attr}} : () ); + _add_attr(\$hcard, $attr, $value, $story_style, $parent_attr, \$parent_started) + if $value; + } + if ($parent_started) { + $hcard .= qq(\n); + next; + } + } + + # Allow bare attributes and aliases + my $value = _get_meta( $attr, $alias{$attr} ? @{$alias{$attr}} : () ); + _add_attr(\$hcard, $attr, $value, $story_style) if $value; + + # Allow typed attributes + if ($attr_types{ $attr }) { + # TODO: need to support $meta package variables here too + for my $meta (sort keys %blosxom::meta) { + # Search for all metadata beginning with $attr or aliases + for my $a ( $attr, $alias{$attr} ? @{$alias{$attr}} : () ) { + if (lc $meta =~ m/^$a[^a-z]+(\w+)$/) { + _add_attr(\$hcard, 'value', $blosxom::meta{ $meta }, $story_style, $attr, undef, $1); + } + } + } + + # Allow standalone types + for my $type ( sort keys %{ $attr_types_standalone{ $attr } } ) { + if (my $value = _get_meta( $type )) { + _add_attr(\$hcard, 'value', $value, $story_style, $attr, undef, + $alias_types{ $type } || $type); + } + + } + } + } + $hcard .= qq(\n); + # debug(2, "hcard $hcard\n"); + + my $autoappend = _get_meta( 'hcard_autoappend' ); + $autoappend = $config{auto_append_to_body} unless defined $autoappend; + return 1 unless $autoappend; + + $$body_ref .= "\n\n$hcard\n\n"; + + return 1; +} + +1; + +__END__ + +=head1 NAME + +uf_hcard_meta - plugin to create an 'hcard' microformat tag from post +metadata + +=head1 DESCRIPTION + +uf_hcard_meta is a plugin to create an 'hcard' microformat tag from +metadata in your post. The microformat tag is created in the +$uf_hcard_meta::hcard story variable for use in templates or by other +plugins, or if the 'auto_append_to_body' config variable is set (it is +by default), uf_hcard_meta will append the tag to your story body +automatically. + +The following metadata items are supported. By and large the official +hcard attribute name is supported, and sometimes one or aliases +(labelled alt below) may also be supported. See the hcard definition at +http://www.microformats.org/wiki/hcard for definitions and discussion +of attributes and usage. + +=head2 REQUIRED METADATA ITEMS + +=over 4 + +=item fn (alt: name) - full name + +=back + +=head2 OPTIONAL METADATA ITEMS + +=over 4 + +=item address-type + +=item post-office-box (alt: pobox) + +=item extended-address + +=item street-address (alt: street) + +=item locality (alt: suburb, city) + +=item region (alt: state) + +=item postal-code (alt: postcode) + +=item country-name (alt: country) + +=item agent + +=item bday + +=item cell (alt: mobile) + +=item email + +=item fax + +=item key + +=item label + +=item latitude + +=item longitude + +=item logo + +=item mailer + +=item honorific-prefix + +=item given-name + +=item additional-name + +=item family-name + +=item honorific-suffix + +=item nickname + +=item note + +=item organization-name (alt: org, organization, organisation) + +=item organization-unit + +=item photo + +=item rev + +=item role + +=item sort-string + +=item sound + +=item tel (alt: telephone, phone) + +And see also the Telephone Element Handling section below. + +=item tz + +=item uid + +=item uri + +=back + +=head2 Telephone Element Handling + +hcard telephone numbers may have type attributes, and because most people have +multiple telephone numbers, uf_hcard_meta also supports decorating the 'tel' +element (or its aliases) with one or more hcard telephone types, just suffixed +on the end of the element and separated by hyphens or underscores. For instance, +all of the following are valid telephone number entries for uf_hcard_meta: + + Tel: 02 8669 0001 + Phone: 8669 0002 + Fax: +612 8669 0003 + Cell: 02 8669 0004 + Mobile: 0401 8669 0005 + Tel-Work: 123 456 7890 + Phone-Work-Direct-Pref-Msg: +1 232 868 7123 + Telephone-Home: 02 8669 0006 + +=head2 Config Elements + +uf_hcard_meta also supports a couple of config elements that can be used to +override plugin config data on a per-story basis: + +=over 4 + +=item HCard-Class (metamail) / hcard_class (meta) + +This class (or list of classes) is appended to the class list applied to the +top-level hcard element in the rendered hcard i.e. it overrides the +'class' config variable. + +=item HCard-Autoappend (metamail) / hcard_autoappend (meta) + +This is a flag (0 or 1) indicating whether the rendered hcard should be +automatically appended to the story body. It overrides the 'auto_append_to_body' +config variable. + +=item HCard-Style (metamail) / hcard_style (meta) + +One of the following styles: 'div-span', 'ul', 'dl', used to render the +hcard. It overrides the 'style' config variable. + +=back + +=head1 EXAMPLES + +An simple example hcard for me: + + Name: Gavin Carr + Org: Open Fusion + Role: Chief Geek + Email: gavin@openfusion.com.au + URL: http://www.openfusion.net/ + POBox: PO Box 1222 + Suburb: Wahroonga + State: NSW + Postcode: 2076 + Country: Australia + +=head1 USAGE + +uf_hcard_meta should be loaded after the meta plugins (meta +itself, or the metaclear/metamail/metadir/metafile family). + +=head1 SEE ALSO + +Microformats.org: http://www.microformats.org/, http://microformats.org/wiki/hcard. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 BUGS + +Probably, since hcards can be pretty horrendously complicated - please +report to the author. Also, this plugin is pretty alpha - I'm not sure +of quite a few of the interface elements, and would welcome input on how +attributes etc. should be represented. + +I also make no guarantees about backwards compatibility - future releases +may break existing hcards, so use at your own risk. + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl:sw=4 diff --git a/gavinc/uf_xfolk_meta b/gavinc/uf_xfolk_meta new file mode 100644 index 0000000..4f310e5 --- /dev/null +++ b/gavinc/uf_xfolk_meta @@ -0,0 +1,234 @@ +# Blosxom Plugin: uf_xfolk_meta +# Author(s): Gavin Carr +# Version: 0.001000 +# Documentation: 'perldoc uf_xfolk_meta' + +package uf_xfolk_meta; + +use strict; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configurable variables ----- + +my %config = ( + + # URL to use as base URL for tag links + tagbase => "$blosxom::url/tags", + + # Extra CSS classes to add to the microformat container e.g. to turn display off + class => '', + #class => 'nodisplay', + + # Whether to automatically add microformat to story bodies. If not set, + # you must explicitly add $uf_adr_meta::adr to a template somewhere. + auto_append_to_body => 1, + + # What markup style to use for your adr, if auto-appending. + # 3 styles are currently defined: + # 'div-span' uses a 'div' elt for the container, and 'span' elements for the fields + # 'ul' uses a 'ul' list for the container, and 'li' elements for the fields + # 'dl' uses a 'dl' list for the container, 'dt' elements for field names, and + # 'dd' elements for the fields themselves + #style => 'div-span', + #style => 'ul', + style => 'dl', + +); + +# -------------------------------- + +use vars qw($xfolk); + +# Attributes which if set will cause us to skip this plugin (looks like an hcard) +my @skip_attr = qw(fn name); + +$config{style} = 'div-span' unless $config{style} eq 'ul' or $config{style} eq 'dl'; + +sub start { 1 } + +# Return the first existing metadata item key and value given a list of keys +sub _get_meta { + for my $attr ( @_ ) { + my $meta_attr = $attr; + $meta_attr =~ s/-/_/g; + my $value = $blosxom::meta{$meta_attr}; + $value = eval "\$meta::$attr" unless defined $value; + return wantarray ? ( $attr, $value ) : $value if defined $value; + } + return wantarray ? () : undef; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + # Skip if any of the @skip_attr are set + for (@skip_attr) { + return 1 if $blosxom::meta{$_} || eval "\$meta::$_"; + } + + my $story_style = _get_meta( 'xfolk_style' ) || $config{style}; + my $ctag = $story_style eq 'div-span' ? 'div' : $story_style; + my $etag = $story_style eq 'div-span' ? 'span' : + $story_style eq 'ul' ? 'li' : 'dd'; + + # Required metadata + my $url = _get_meta('url', 'taggedlink'); + my $title = _get_meta('title'); + my $tags = _get_meta('tags'); + my $description = _get_meta('description'); + return 1 unless defined $url && defined $title; + + $xfolk = ''; + my $container_classes = 'xfolkentry'; + if (my $meta_class = _get_meta('xfolk_class')) { + $container_classes .= " $meta_class"; + } + else { + $container_classes .= " $config{class}" if $config{class}; + } + $xfolk .= qq(<$ctag class="$container_classes">\n); + $xfolk .= qq(
URL
) if $story_style eq 'dl'; + $xfolk .= qq(<$etag class="xfolk_link">$title\n); + if ($tags) { + $xfolk .= qq(
Tags
) if $story_style eq 'dl'; + $xfolk .= qq(<$etag class="xfolk_tags">); + my @tags = (); + for (split /\s*,\s*/, $tags) { + push @tags, qq(); + } + $xfolk .= join ', ', @tags if @tags; + $xfolk .= qq(\n); + } + if ($description) { + $xfolk .= qq(
Description
) if $story_style eq 'dl'; + $xfolk .= qq(<$etag class="description">$description\n) + } + $xfolk .= qq(\n); + # debug(1, "uf_xfolk_meta: $xfolk\n"); + + my $autoappend = _get_meta( 'xfolk_autoappend' ); + $autoappend = $config{auto_append_to_body} unless defined $autoappend; + return 1 unless $autoappend; + + $$body_ref .= "\n\n$xfolk\n\n"; + + return 1; +} + +1; + +__END__ + +=head1 NAME + +uf_xfolk_meta - plugin to create a 'xfolk' (bookmark) microformat tag +from post metadata + +=head1 DESCRIPTION + +uf_xfolk_meta is a plugin to create an 'xfolk' (bookmark) microformat tag +from metadata in your post. The microformat tag is created in the +$uf_xfolk_meta::xfolk variable for use in templates or by other plugins, +or if the 'auto_append_to_body' config variable is set (it is by default), +uf_xfolk_meta will append the tag to your story body automatically. + +=head2 REQUIRED METADATA ITEMS + +=over 4 + +=item url (or taggedlink) + +The URL for the bookmarked page. + +=item title + +The title to use for the bookmarked page. + +=back + +If any required metadata is missing the plugin just skips the story. + +=head2 OPTIONAL METADATA ITEMS + +=over 4 + +=item tags + +Comma-separated list of tags applying to the bookmarked page. + +=item description + +Description or summary of the bookmarked page. + +=back + +=head2 Config Elements + +uf_xfolk_meta also supports a couple of config elements that can be used to +override plugin config data on a per-story basis: + +=over 4 + +=item XFolk-Class (metamail) / xfolk_class (meta) + +This class (or list of classes) is appended to the class list applied to the +top-level xfolk element in the rendered xfolk i.e. it overrides the +'class' config variable. + +=item XFolk-Autoappend (metamail) / xfolk_autoappend (meta) + +This is a flag (0 or 1) indicating whether the rendered xfolk should be +automatically appended to the story body. It overrides the 'auto_append_to_body' +config variable. + +=item XFolk-Style (metamail) / xfolk_style (meta) + +One of the following styles: 'div-span', 'ul', 'dl', used to render the xfolk. +It overrides the 'style' config variable. + +=back + +=head1 USAGE + +uf_xfolk_meta should be loaded after the meta plugins (meta +itself, or the metaclear/metamail/metadir/metafile family). + +=head1 SEE ALSO + +Microformats.org: http://www.microformats.org/, http://microformats.org/wiki/xfolk. + +Blosxom: http://blosxom.sourceforge.net/ + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl