switch to map as a collection method - thanks to jnthn (and good luck with rakudo...
[catagits/Web-Simple.git] / examples / bloggery / bloggery.cgi
CommitLineData
5c33dda5 1use FindBin;
2use lib $FindBin::Bin.'/code';
3use Web::Simple 'Bloggery';
4
5package Bloggery::PostList;
6
7use File::stat;
8
9sub from_dir {
10 my ($class, $dir) = @_;
11 bless ({ dir => $dir }, $class);
12}
13
14sub all {
15 my ($self) = @_;
16 map { Bloggery::Post->from_file($_) }
17 sort { stat($a)->mtime <=> stat($b)->mtime }
18 grep { !/\.summary\.html$/ }
19 glob($self->{dir}.'/*.html');
20}
21
22sub post {
23 my ($self, $name) = @_;
24 my $file = $self->{dir}."/${name}.html";
25 return unless $file && -f $file;
26 return Bloggery::Post->from_file($file);
27}
28
d2a1d0c7 29sub map {
30 my ($self, $code) = @_;
31 map $code->($_), $self->all;
32}
33
5c33dda5 34package Bloggery::Post;
35
36sub from_file {
37 my ($class, $file) = @_;
38 bless({ file => $file }, $class);
39}
40
41sub name {
42 my $name = shift->{file};
43 $name =~ s/.*\///;
44 $name =~ s/\.html$//;
45 $name;
46}
47
48sub title {
49 my $title = shift->name;
50 $title =~ s/-/ /g;
51 $title;
52}
53
54sub html {
55 \do { local (@ARGV, $/) = shift->{file}; <> };
56}
57
58sub summary_html {
59 my $file = shift->{file};
60 $file =~ s/\.html$/.summary.html/;
61 return \'<p>No summary</p>' unless -f $file;
62 \do { local (@ARGV, $/) = $file; <> };
63}
64
65package Bloggery;
66
67default_config(
68 title => 'Bloggery',
69 posts_dir => $FindBin::Bin.'/posts',
70);
71
72sub post_list {
73 my ($self) = @_;
74 $self->{post_list}
75 ||= Bloggery::PostList->from_dir(
76 $self->config->{posts_dir}
77 );
78}
79
80sub post {
81 my ($self, $post) = @_;
82 $self->post_list->post($post);
83}
84
85dispatch [
86 sub (.html) {
87 filter_response { $self->render_html($_[1]) },
88 },
89 sub (GET + /) {
90 $self->redispatch('index.html')
91 },
92 sub (GET + /index) {
93 $self->post_list
94 },
95 sub (GET + /*) {
96 $self->post($_[1]);
97 },
98 sub (GET) {
99 [ 404, [ 'Content-type', 'text/plain' ], [ 'Not found' ] ]
100 },
101 sub {
102 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
103 },
104];
105
106sub render_html {
107 my ($self, $data) = @_;
108 use HTML::Tags;
109 return $data if ref($data) eq 'ARRAY';
110 return [
111 200,
112 [ 'Content-type', 'text/html' ],
113 [
114 HTML::Tags::to_html_string(
115 <html>,
116 <head>,
117 <title>, $self->title_for($data), </title>,
118 </head>,
119 <body>,
120 <h1>, $self->title_for($data), </h1>,
121 <div id="main">,
122 $self->main_html_for($data),
123 </div>,
124 </body>,
125 </html>
126 )
127 ]
128 ];
129}
130
131sub title_for {
132 my ($self, $data) = @_;
133 if ($data->isa('Bloggery::Post')) {
134 return $data->title;
135 }
136 return $self->config->{title};
137}
138
139sub main_html_for {
140 my ($self, $data) = @_;
141 use HTML::Tags;
142 if ($data->isa('Bloggery::Post')) {
143 $data->html
144 } elsif ($data->isa('Bloggery::PostList')) {
145 <ul>,
d2a1d0c7 146 $data->map(sub {
5c33dda5 147 my $path = '/'.$_->name.'.html';
148 <li>,
149 <h4>, <a href="$path">, $_->title, </a>, </h4>,
150 <span class="summary">, $_->summary_html, </span>,
151 </li>;
d2a1d0c7 152 }),
5c33dda5 153 </ul>;
154 } else {
155 <h2>, "Don't know how to render $data", </h2>;
156 }
157}
158
159Bloggery->run_if_script;