7 has pages => (is => 'lazy');
9 has filters => (is => 'lazy');
11 has _layout_zoom => (is => 'lazy');
15 pages_dir => 'share/content',
16 template_dir => 'share/skin',
22 SCSite::PageSet->new(base_dir => io->dir($self->config->{pages_dir}))
27 require SCSite::SubListFilter;
28 +{ SubList => SCSite::SubListFilter->new }
31 sub dispatch_request {
34 $self->_http_response(500 => 'text/plain' => 'Not implemented');
37 $self->_page_http_response(200 => $self->_find_page('index'));
40 [ 302, [ 'Location' => "/$_[1]/" ], [] ]
43 my ($code, $page) = map {
44 $_ ? (200, $_) : (404, $self->_error_page(404))
45 } $self->_find_page($_[1]);
46 $self->_page_http_response($code => $page);
51 my ($self, $code) = @_;
52 $self->_find_page("error_${code}");
56 my ($self, $path) = @_;
57 $self->pages->get({ path => $path });
61 my ($self, $code, $type, $content) = @_;
62 [ $code, [ 'Content-type' => $type ], [ $content ] ];
65 sub _page_http_response {
66 my ($self, $code, $page) = @_;
67 [ $code, [ 'Content-type' => 'text/html' ], $self->_render_page($page) ];
71 my ($self, $page) = @_;
72 my $zoom = $self->_layout_zoom;
73 $zoom->select('.title')->replace_content($page->title)
74 ->select('meta[name=description]')->replace_content($page->description)
75 ->select('meta[name=keywords]')->replace_content($page->keywords)
76 ->select('.main')->replace_content(\$page->body)
77 ->select('.SubList')->collect({
78 filter => $self->filters->{SubList}->callback_for($page),
84 sub _build__layout_zoom {
86 HTML::Zoom->from_file(
87 io->dir($self->config->{template_dir})->catfile('layout.html')
92 return $_[0]->to_psgi_app if caller(1);
94 my @config_keys = keys %{{$class->default_config}};
97 Getopt::Long::GetOptions(
98 map +("$_=s" => \$config{$_}), @config_keys
100 delete $config{$_} for grep !defined($config{$_}), keys %config;
101 my $new = $class->new(config => \%config);
105 __PACKAGE__->run_if_script;