From: Matt S Trout Date: Wed, 9 Feb 2011 05:23:24 +0000 (+0000) Subject: sidebar filter X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fc436d2e3878fef4e7c28bed798ac6bc2247771b;p=scpubgit%2FSCS.git sidebar filter --- diff --git a/lib/SCSite.pm b/lib/SCSite.pm index ffa9cb2..7d821d4 100644 --- a/lib/SCSite.pm +++ b/lib/SCSite.pm @@ -25,7 +25,11 @@ sub _build_pages { sub _build_filters { my ($self) = @_; require SCSite::SubListFilter; - +{ SubList => SCSite::SubListFilter->new } + require SCSite::SidebarFilter; + +{ + map +($_ => "SCSite::${_}Filter"->new_from_site($self)), + qw(SubList Sidebar) + } } sub dispatch_request { @@ -70,13 +74,19 @@ sub _page_http_response { sub _render_page { my ($self, $page) = @_; my $zoom = $self->_layout_zoom; - $zoom->select('.title')->replace_content($page->title) + my %filters = %{$self->filters}; + $zoom->select('.page.title')->replace_content($page->title) ->select('meta[name=description]')->replace_content($page->description) ->select('meta[name=keywords]')->replace_content($page->keywords) ->select('.main')->replace_content(\$page->body) - ->select('.SubList')->collect({ - filter => $self->filters->{SubList}->callback_for($page), - passthrough => 1, + ->apply(sub { + foreach my $fname (sort keys %filters) { + my $cb = $filters{$fname}->callback_for($page); + $_ = $_->select(".${fname}")->collect({ + filter => $cb, passthrough => 1 + }); + } + $_ }) ->to_fh } diff --git a/lib/SCSite/Filter.pm b/lib/SCSite/Filter.pm index bbf442a..6897fc7 100644 --- a/lib/SCSite/Filter.pm +++ b/lib/SCSite/Filter.pm @@ -4,6 +4,8 @@ use Moo::Role; requires '_filter_stream'; +sub new_from_site { shift->new } + sub callback_for { my ($self, @args) = @_; sub { diff --git a/lib/SCSite/LatestPageSet.pm b/lib/SCSite/LatestPageSet.pm index 327fb2c..dbeca56 100644 --- a/lib/SCSite/LatestPageSet.pm +++ b/lib/SCSite/LatestPageSet.pm @@ -8,9 +8,10 @@ has _max_entries => (is => 'ro', required => 1, init_arg => 'max_entries'); sub flatten { my ($self) = @_; my @sorted = sort { - $a->created cmp $b->created + $b->created cmp $a->created } $self->_parent->flatten; - $self->_max_entries ? @sorted[0..$self->_max_entries-1] : @sorted; + my $max = $self->_max_entries||0; + @sorted > $max ? @sorted[0..$max-1] : @sorted; } sub map { diff --git a/lib/SCSite/Page.pm b/lib/SCSite/Page.pm index a0e5c15..cba4d6a 100644 --- a/lib/SCSite/Page.pm +++ b/lib/SCSite/Page.pm @@ -8,12 +8,17 @@ has $_ => (is => 'ro') for qw(title description keywords body created path); has "_$_" => (is => 'ro', init_arg => $_) for qw(page_set); sub children { - my ($self) = @_; + my ($self, %args) = @_; + if (my $at = delete $args{at_depth}) { +warn "Here, $at"; + @args{qw(min_depth max_depth)} = ($at-1, $at); + } my $ps = $self->_page_set; (ref $ps)->new( top_dir => $ps->base_dir, base_dir => io->dir($ps->base_dir)->catdir($self->path), - max_depth => 1 + max_depth => 1, + %args, ); } diff --git a/lib/SCSite/PageSet.pm b/lib/SCSite/PageSet.pm index 3f7d307..a1e12f5 100644 --- a/lib/SCSite/PageSet.pm +++ b/lib/SCSite/PageSet.pm @@ -11,6 +11,7 @@ use Moo; has top_dir => (is => 'ro', lazy => 1, builder => 'base_dir'); has base_dir => (is => 'ro', required => 1); has max_depth => (is => 'ro', default => quote_sub q{ 0 }); +has min_depth => (is => 'ro', default => quote_sub q{ 0 }); has rel_path => (is => 'lazy'); @@ -31,7 +32,7 @@ sub get { }}->filter(sub { $_->filename =~ /^\Q${file}\E${\$self->_types_re}$/ and $type = $1 }) - ->all_files; + ->${\sub { $_[0]->exists ? $_[0]->all_files : () }}; die "multiple files found for ${\$spec->{path}}:\n".join "\n", @poss if @poss > 1; return undef unless @poss; @@ -45,18 +46,35 @@ sub map { [ map $mapper->($_), $self->flatten ] } +sub _depth_under_base { + my ($self, $path) = @_; + File::Spec->splitdir(File::Spec->abs2rel($path, $self->base_dir->name)) +} + sub flatten { my ($self) = @_; + return unless (my $base = $self->base_dir)->exists; my %seen; my $slash = io->dir('/'); + my $min = $self->min_depth; + my @dirs = map $min ? $_->all_dirs($min) : $_, $base; map { my ($path, $type) = $_->name =~ /^(.*)${\$self->_types_re}$/; $self->${\"_inflate_${type}"}( - $slash->catdir(File::Spec->abs2rel($path, $self->top_dir->name)), $_->all + $slash->catdir(File::Spec->abs2rel($path, $self->top_dir->name)), + $_->all ); - } io->dir($self->base_dir) - ->filter(sub { $_->filename =~ /${\$self->_types_re}$/ }) - ->all_files($self->max_depth) + } map { + $_->filter(sub { $_->filename =~ /${\$self->_types_re}$/ }) + ->all_files($self->max_depth - $min) + } map + $min + ? do { + # can't use ->all_dirs($min) since we only want the final level + my @x = ($_); @x = map $_->all_dirs, @x for 1..$min; @x + } + : $_, + $self->base_dir; } sub latest { diff --git a/lib/SCSite/SidebarFilter.pm b/lib/SCSite/SidebarFilter.pm new file mode 100644 index 0000000..d5c28ad --- /dev/null +++ b/lib/SCSite/SidebarFilter.pm @@ -0,0 +1,75 @@ +package SCSite::SidebarFilter; + +use Moo; + +with 'SCSite::Filter'; + +has _page_set => (is => 'ro', required => 1); + +sub new_from_site { + my ($class, $site) = @_; + $class->new(_page_set => $site->pages); +} + +sub _latest_news { + shift->_page_set + ->get({ path => '/news/archive' }) + ->children(at_depth => 3) + ->latest(2) + ->flatten; +} + +sub _latest_news_archives { + shift->_page_set + ->get({ path => '/news/archive' }) + ->${\sub { # archive page plus three latest per-month + my $o = shift; + ($o, $o->children(at_depth => 2)->latest(3)->flatten) + }}; +} + +sub _latest_blog_posts { + shift->_page_set + ->get({ path => '/blog' }) + ->children(min_depth => 2, max_depth => 0) + ->latest(4) + ->flatten; +} + +sub _sidebar_structure { + my ($self) = @_; + [ + [ 'NEWS', + [ 'Latest News Items', $self->_latest_news ], + [ 'Archives', $self->_latest_news_archives ], + ], + [ 'BLOGS', + [ 'Latest Blog Posts', $self->_latest_blog_posts ], + ], + ]; +} + +sub _filter_stream { + my ($self, $stream) = @_; + my @blocks = @{$self->_sidebar_structure}; + $stream->select('.sidebar.block')->repeat([ + map { my ($t, @seg) = @$_; sub { + $_->select('.sidebar.title')->replace_content($t) + ->select('.sidebar.segment')->repeat([ + map { my ($s, @e) = @$_; warn $s; warn @e; sub { + $_->select('.sidebar.subtitle')->replace_content($s) + ->select('.sidebar.entries')->repeat_content([ + map { my $e = $_; sub { + $_->select('.entry.title') + ->replace_content($e->title) + ->select('.entry.link') + ->set_attribute(href => $e->path) + } } @e + ]) + } } @seg + ]) + } } @blocks + ]) +} + +1; diff --git a/share/skin/layout.html b/share/skin/layout.html index e459fb3..cf54d8b 100644 --- a/share/skin/layout.html +++ b/share/skin/layout.html @@ -1,11 +1,11 @@ - page title + page title -
page title
+
page title