Commit | Line | Data |
89166c1b |
1 | #!/usr/bin/perl |
2 | |
5c33dda5 |
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 | |
d2a1d0c7 |
31 | sub map { |
32 | my ($self, $code) = @_; |
33 | map $code->($_), $self->all; |
34 | } |
35 | |
5c33dda5 |
36 | package Bloggery::Post; |
37 | |
38 | sub from_file { |
39 | my ($class, $file) = @_; |
40 | bless({ file => $file }, $class); |
41 | } |
42 | |
43 | sub name { |
44 | my $name = shift->{file}; |
45 | $name =~ s/.*\///; |
46 | $name =~ s/\.html$//; |
47 | $name; |
48 | } |
49 | |
50 | sub title { |
51 | my $title = shift->name; |
52 | $title =~ s/-/ /g; |
53 | $title; |
54 | } |
55 | |
56 | sub html { |
57 | \do { local (@ARGV, $/) = shift->{file}; <> }; |
58 | } |
59 | |
60 | sub 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 | |
67 | package Bloggery; |
68 | |
69 | default_config( |
70 | title => 'Bloggery', |
71 | posts_dir => $FindBin::Bin.'/posts', |
72 | ); |
73 | |
74 | sub post_list { |
75 | my ($self) = @_; |
76 | $self->{post_list} |
77 | ||= Bloggery::PostList->from_dir( |
78 | $self->config->{posts_dir} |
79 | ); |
80 | } |
81 | |
82 | sub post { |
83 | my ($self, $post) = @_; |
84 | $self->post_list->post($post); |
85 | } |
86 | |
92e23550 |
87 | dispatch { |
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 | |
108 | sub 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 | |
133 | sub title_for { |
134 | my ($self, $data) = @_; |
135 | if ($data->isa('Bloggery::Post')) { |
136 | return $data->title; |
137 | } |
138 | return $self->config->{title}; |
139 | } |
140 | |
141 | sub 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 | |
161 | Bloggery->run_if_script; |