Commit | Line | Data |
5c33dda5 |
1 | #!/usr/bin/perl |
2 | |
3 | use FindBin; |
4 | use lib $FindBin::Bin.'/code'; |
5 | use Web::Simple 'Bloggery'; |
6 | |
7 | package Bloggery::PostList; |
8 | |
9 | use File::stat; |
10 | |
11 | sub from_dir { |
12 | my ($class, $dir) = @_; |
13 | bless ({ dir => $dir }, $class); |
14 | } |
15 | |
16 | sub 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 | |
24 | sub 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 | |
31 | package Bloggery::Post; |
32 | |
33 | sub from_file { |
34 | my ($class, $file) = @_; |
35 | bless({ file => $file }, $class); |
36 | } |
37 | |
38 | sub name { |
39 | my $name = shift->{file}; |
40 | $name =~ s/.*\///; |
41 | $name =~ s/\.html$//; |
42 | $name; |
43 | } |
44 | |
45 | sub title { |
46 | my $title = shift->name; |
47 | $title =~ s/-/ /g; |
48 | $title; |
49 | } |
50 | |
51 | sub html { |
52 | \do { local (@ARGV, $/) = shift->{file}; <> }; |
53 | } |
54 | |
55 | sub 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 | |
62 | package Bloggery; |
63 | |
64 | default_config( |
65 | title => 'Bloggery', |
66 | posts_dir => $FindBin::Bin.'/posts', |
67 | ); |
68 | |
69 | sub post_list { |
70 | my ($self) = @_; |
71 | $self->{post_list} |
72 | ||= Bloggery::PostList->from_dir( |
73 | $self->config->{posts_dir} |
74 | ); |
75 | } |
76 | |
77 | sub post { |
78 | my ($self, $post) = @_; |
79 | $self->post_list->post($post); |
80 | } |
81 | |
82 | dispatch [ |
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 | |
103 | sub 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 | |
128 | sub title_for { |
129 | my ($self, $data) = @_; |
130 | if ($data->isa('Bloggery::Post')) { |
131 | return $data->title; |
132 | } |
133 | return $self->config->{title}; |
134 | } |
135 | |
136 | sub 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 | |
156 | Bloggery->run_if_script; |