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