From: Matt S Trout Date: Thu, 3 Feb 2011 23:16:16 +0000 (+0000) Subject: basic page rendering X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=5cc6d9e26390465dcffdbae34f081eadbf76956a;p=scpubgit%2FSCS.git basic page rendering --- diff --git a/lib/SCSite.pm b/lib/SCSite.pm new file mode 100644 index 0000000..d0a9627 --- /dev/null +++ b/lib/SCSite.pm @@ -0,0 +1,118 @@ +package SCSite; + +use IO::All; +use SCSite::PageSet; +use Web::Simple; + +{ + package SCSite::Link; use Moo; has $_ => (is => 'ro') for qw(title to); +} + +has _topbar => (is => 'ro', default => sub { [ + map SCSite::Link->new(title => $_->[0], to => $_->[1] ), + map [ /^(.*?)\s+(\S+)$/ ], + split("\n", <<'ENDBAR') +Home / +About /about +News /news +Catalyst /catalyst +Servers /servers +Professional Services /services +Blogs /blog +ENDBAR + ] } +); + +has pages => (is => 'lazy'); + +has _layout_zoom => (is => 'lazy'); + +sub default_config { + ( + pages_dir => 'share/content', + template_dir => 'share/skin', + ) +} + +sub _build_pages { + my ($self) = @_; + SCSite::PageSet->new(base_dir => $self->config->{pages_dir}) +} + +sub dispatch_request { + my $self = shift; + sub (/feed/**/) { + $self->_http_response(500 => 'text/plain' => 'Not implemented'); + }, + sub (/) { + $self->_page_http_response(200 => $self->_find_page('index')); + }, + sub (/**) { + [ 302, [ 'Location' => "/$_[1]/" ], [] ] + }, + sub (/**/) { + my ($code, $page) = map { + $_ ? (200, $_) : (404, $self->_error_page(404)) + } $self->_find_page($_[1]); + $self->_page_http_response($code => $page); + } +} + +sub _error_page { + my ($self, $code) = @_; + $self->_find_page("error_${code}"); +} + +sub _find_page { + my ($self, $path) = @_; + $self->pages->get({ path => $path }); +} + +sub _http_response { + my ($self, $code, $type, $content) = @_; + [ $code, [ 'Content-type' => $type ], [ $content ] ]; +} + +sub _page_http_response { + my ($self, $code, $page) = @_; + [ $code, [ 'Content-type' => 'text/html' ], $self->_render_page($page) ]; +} + +sub _render_page { + my ($self, $page) = @_; + my $zoom = $self->_layout_zoom; + $zoom->select('.title')->replace_content($page->title) + ->select('meta[name=description]')->replace_content($page->description) + ->select('meta[name=keywords]')->replace_content($page->keywords) + ->select('.topbar_entries')->repeat_content([ + map { my $e = $_; sub { + $_->select('.entry')->replace_content($e->title) + ->then->set_attribute(href => $e->to) + } } @{$self->_topbar} + ]) + ->select('.main')->replace_content(\$page->body) + ->to_fh +} + +sub _build__layout_zoom { + my ($self) = @_; + HTML::Zoom->from_file( + io->dir($self->config->{template_dir})->catfile('layout.html') + )->memoize; +} + +sub run_if_script { + return $_[0]->to_psgi_app if caller(1); + my $class = shift; + my @config_keys = keys %{{$class->default_config}}; + require Getopt::Long; + my %config; + Getopt::Long::GetOptions( + map +("$_=s" => \$config{$_}), @config_keys + ); + delete $config{$_} for grep !defined($config{$_}), keys %config; + my $new = $class->new(config => \%config); + $new->run(@_) +} + +__PACKAGE__->run_if_script; diff --git a/lib/SCSite/PageSet.pm b/lib/SCSite/PageSet.pm index d2d440a..559038b 100644 --- a/lib/SCSite/PageSet.pm +++ b/lib/SCSite/PageSet.pm @@ -16,7 +16,7 @@ sub get { $spec->{path} or die "path is required to get"; my ($dir, $file) = $spec->{path} =~ m{^(?:(.*)/)?([^/]+)$}; my $type; - my @poss = io($self->base_dir)->${\sub { + my @poss = io->dir($self->base_dir)->${\sub { my $io = shift; defined($dir) ? $io->catdir($dir) : $io }}->filter(sub { $_->filename =~ /\Q${file}\E\.(html|md)/ and $type = $1 }) diff --git a/share/skin/layout.html b/share/skin/layout.html new file mode 100644 index 0000000..e85c0de --- /dev/null +++ b/share/skin/layout.html @@ -0,0 +1,24 @@ + + + page title + + + + +
page title
+
+ +
+
+ +
+
+ +