change plugin interface to use named parameters for flexability
[ikiwiki] / IkiWiki / Plugin / inline.pm
1 #!/usr/bin/perl
2 # Page inlining and blogging.
3 package IkiWiki::Plugin::inline;
4
5 use warnings;
6 use strict;
7 use IkiWiki;
8
9 sub import { #{{{
10         IkiWiki::hook(type => "preprocess", id => "inline", 
11                 call => \&IkiWiki::preprocess_inline);
12 } # }}}
13
14 # Back to ikiwiki namespace for the rest, this code is very much
15 # internal to ikiwiki even though it's separated into a plugin.
16 package IkiWiki;
17         
18 sub preprocess_inline (@) { #{{{
19         my %params=@_;
20
21         if (! exists $params{pages}) {
22                 return "";
23         }
24         if (! exists $params{archive}) {
25                 $params{archive}="no";
26         }
27         if (! exists $params{show} && $params{archive} eq "no") {
28                 $params{show}=10;
29         }
30         add_depends($params{page}, $params{pages});
31
32         my $ret="";
33         
34         if (exists $params{rootpage}) {
35                 # Add a blog post form, with a rss link button.
36                 my $formtemplate=HTML::Template->new(blind_cache => 1,
37                         filename => "$config{templatedir}/blogpost.tmpl");
38                 $formtemplate->param(cgiurl => $config{cgiurl});
39                 $formtemplate->param(rootpage => $params{rootpage});
40                 if ($config{rss}) {
41                         $formtemplate->param(rssurl => rsspage(basename($params{page})));
42                 }
43                 $ret.=$formtemplate->output;
44         }
45         elsif ($config{rss}) {
46                 # Add a rss link button.
47                 my $linktemplate=HTML::Template->new(blind_cache => 1,
48                         filename => "$config{templatedir}/rsslink.tmpl");
49                 $linktemplate->param(rssurl => rsspage(basename($params{page})));
50                 $ret.=$linktemplate->output;
51         }
52         
53         my $template=HTML::Template->new(blind_cache => 1,
54                 filename => (($params{archive} eq "no") 
55                                 ? "$config{templatedir}/inlinepage.tmpl"
56                                 : "$config{templatedir}/inlinepagetitle.tmpl"));
57         
58         my @pages;
59         foreach my $page (blog_list($params{pages}, $params{show})) {
60                 next if $page eq $params{page};
61                 push @pages, $page;
62                 $template->param(pagelink => htmllink($params{page}, $page));
63                 $template->param(content => get_inline_content($params{page}, $page))
64                         if $params{archive} eq "no";
65                 $template->param(ctime => scalar(gmtime($pagectime{$page})));
66                 $ret.=$template->output;
67         }
68         
69         # TODO: should really add this to renderedfiles and call
70         # check_overwrite, but currently renderedfiles
71         # only supports listing one file per page.
72         if ($config{rss}) {
73                 writefile(rsspage($params{page}), $config{destdir},
74                         genrss($params{page}, @pages));
75         }
76         
77         return $ret;
78 } #}}}
79
80 sub blog_list ($$) { #{{{
81         my $globlist=shift;
82         my $maxitems=shift;
83
84         my @list;
85         foreach my $page (keys %pagesources) {
86                 if (globlist_match($page, $globlist)) {
87                         push @list, $page;
88                 }
89         }
90
91         @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
92         return @list if ! $maxitems || @list <= $maxitems;
93         return @list[0..$maxitems - 1];
94 } #}}}
95
96 sub get_inline_content ($$) { #{{{
97         my $parentpage=shift;
98         my $page=shift;
99         
100         my $file=$pagesources{$page};
101         my $type=pagetype($file);
102         if ($type ne 'unknown') {
103                 return htmlize($type, linkify(readfile(srcfile($file)), $parentpage));
104         }
105         else {
106                 return "";
107         }
108 } #}}}
109
110 sub date_822 ($) { #{{{
111         my $time=shift;
112
113         eval q{use POSIX};
114         return POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time));
115 } #}}}
116
117 sub absolute_urls ($$) { #{{{
118         # sucky sub because rss sucks
119         my $content=shift;
120         my $url=shift;
121
122         $url=~s/[^\/]+$//;
123         
124         $content=~s/<a\s+href="(?!http:\/\/)([^"]+)"/<a href="$url$1"/ig;
125         $content=~s/<img\s+src="(?!http:\/\/)([^"]+)"/<img src="$url$1"/ig;
126         return $content;
127 } #}}}
128
129 sub rsspage ($) { #{{{
130         my $page=shift;
131
132         return $page.".rss";
133 } #}}}
134
135 sub genrss ($@) { #{{{
136         my $page=shift;
137         my @pages=@_;
138         
139         my $url="$config{url}/".htmlpage($page);
140         
141         my $template=HTML::Template->new(blind_cache => 1,
142                 filename => "$config{templatedir}/rsspage.tmpl");
143         
144         my @items;
145         foreach my $p (@pages) {
146                 push @items, {
147                         itemtitle => pagetitle(basename($p)),
148                         itemurl => "$config{url}/$renderedfiles{$p}",
149                         itempubdate => date_822($pagectime{$p}),
150                         itemcontent => absolute_urls(get_inline_content($page, $p), $url),
151                 } if exists $renderedfiles{$p};
152         }
153
154         $template->param(
155                 title => $config{wikiname},
156                 pageurl => $url,
157                 items => \@items,
158         );
159         
160         return $template->output;
161 } #}}}
162
163 1