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