tagging: Allow using titles in for related stories.
[matthijs/upstream/blosxom-plugins.git] / gavinc / metamail
1 # Blosxom Plugin: metamail
2 # Author(s): Gavin Carr <gavin@openfusion.com.au>
3 # Version: 0.002000
4 # Documentation: 'perldoc metamail'
5 # Requires: metaclear
6 # Follows: metaclear
7
8 package metamail;
9
10 use strict;
11 use vars qw(%config);
12
13 #use Blosxom::Debug debug_level => 1;
14
15 # --- Configurable variables -----
16
17 %config = ();
18
19 # Headers to consider titles
20 $config{title_headers} = [ qw(Title Subject) ];
21
22 # Headers to keep in the body (required by later plugins, for instance)
23 $config{keep_in_body_headers} = qw(Tags);
24
25 # Whether to unfold (join) multi-line headers
26 $config{unfold_headers} = 1;
27
28 # --------------------------------
29 # __END_CONFIG__
30
31 sub start { 1 };
32
33 sub story {
34   my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
35
36   my %header = ();
37   my ($headers, $body) = split /\n\s*\n/, $$title_ref . "\n" . $$body_ref, 2;
38
39   my $meta = \%blosxom::meta;
40
41   # Walk the headers
42   for my $header ( split /\n(?=\S)/, $headers ) {
43     # Split header into key/value
44     my ($key, $key2, $value);
45     if ($header =~ m/:/) {
46       ($key, $value) = split /:\s*/, $header, 2;  
47     }
48     # For backwards compatibility, assume a header without a : is a title
49     else {
50       $key = $config{title_headers}->[0] || 'Title';
51       $value = $header;
52     }
53     chomp $value;
54     
55     # Unfold
56     $value =~ s/\n //g if $config{unfold_headers};
57
58     # Cache header
59     $header{$key} = $value;
60
61     # Insert into meta namespace
62     $meta->{$key} = $value;
63     # debug(1, "metamail: $key: " . $meta->{$key} . "\n");
64     # Insert lowercase/underscored version as well
65     ($key2 = lc $key) =~ s/-/_/g;
66     if ($key ne $key2) {
67       $meta->{$key2} = $value;
68       # debug(1, "metamail: $key2: " . $meta->{$key2} . "\n");
69     }
70   }
71
72   # Update $$title_ref to the first title_header we can find
73   $$title_ref = '';
74   for (@{$config{title_headers}}) {
75     $$title_ref = $header{$_} and last if $header{$_};
76   }
77
78   # Update body_ref
79   if (my @keep_headers = grep { defined $header{$_} } @{$config{keep_in_body_headers}}) {
80     $$body_ref = join("\n", map { "$_: $header{$_}" } @keep_headers) . "\n" . $body;
81   }
82   else {
83     $$body_ref = $body;
84   }
85
86   return 1;
87 }
88
89 1;
90
91 __END__
92
93 =head1 NAME
94
95 metamail - an alternative to Rael's original L<meta> plugin, supporting
96 mail/RFC822-style headers in posts
97
98 =head1 DESCRIPTION
99
100 metamail is a plugin for loading metadata from the 'headers' in a 
101 blosxom post. Metadata is loaded into a %blosxom::meta hash (instead of
102 into package variables like L<meta>). metamail expects posts to look like 
103 RFC822-style mails i.e. a bunch of headers, where a header is a key (no 
104 whitespace) followed by a colon followed by a value; then an empty line 
105 as a separator; and then the post body.
106
107 metamail loads all headers it finds as variables into the %blosxom::meta
108 hash. It typically creates two entries for each header: the first is named 
109 exactly as the key is given in the header, and the second is the key 
110 converted to lowercase, and with dashes converted to underscores.
111
112 So given the following headers:
113
114     Title: Test Post 1
115     Tags: test, ignore
116     URL: http://www.openfusion.net/
117
118 metamail will create the following %blosxom::meta entries:
119    
120     $blosxom::meta{Title} = 'Test Post 1';
121     $blosxom::meta{title} = 'Test Post 1';
122     $blosxom::meta{Tags} = 'test, ignore';
123     $blosxom::meta{tags} = 'test, ignore';
124     $blosxom::meta{URL} = 'http://www.openfusion.net/';
125     $blosxom::meta{url} = 'http://www.openfusion.net/';
126
127 For backwards compatibility purposes, L<metamail> will treat any header
128 not containing a colon (which is typically the first line title) as the 
129 'Title' of the post, and store it with the first key in 'title_headers'
130 (default is 'Title'). L<metamail> supports the title being anywhere in 
131 the headers, and will report it properly to blosxom, but any plugins 
132 that look directly at the post file may still expect the title 
133 (without a key) to be there in the first line, so that is currently
134 still the recommended convention.
135
136 =head1 USAGE
137
138 This plugin requires the L<metaclear> plugin to reset the %blosxom::meta
139 hash for each story, and should be loaded early, after L<metaclear>, but
140 typically before all other story plugins e.g. as 05metamail. 
141
142 This is an *alternative* to the L<meta> plugin, so should usually be used 
143 _instead_ of L<meta>, not as well.
144
145 =head1 SEE ALSO
146
147 L<metaclear>, L<metadir>, L<metafile>.
148
149 L<meta>, Rael Dornfest's original metadata plugin
150
151 Blosxom: http://blosxom.sourceforge.net/
152
153 =head1 AUTHOR
154
155 Gavin Carr <gavin@openfusion.com.au>, http://www.openfusion.net/
156
157 =head1 LICENSE
158
159 Copyright 2007, Gavin Carr.
160
161 This plugin is licensed under the same terms as blosxom itself i.e.
162
163 Permission is hereby granted, free of charge, to any person obtaining a
164 copy of this software and associated documentation files (the "Software"),
165 to deal in the Software without restriction, including without limitation
166 the rights to use, copy, modify, merge, publish, distribute, sublicense,
167 and/or sell copies of the Software, and to permit persons to whom the
168 Software is furnished to do so, subject to the following conditions:
169
170 The above copyright notice and this permission notice shall be included
171 in all copies or substantial portions of the Software.
172
173 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
174 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
175 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
176 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
177 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
178 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
179 OTHER DEALINGS IN THE SOFTWARE.
180
181 =cut
182
183 # vim:ft=perl