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 {
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
}
requires '_filter_stream';
+sub new_from_site { shift->new }
+
sub callback_for {
my ($self, @args) = @_;
sub {
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 {
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,
);
}
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');
}}->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;
[ 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 {
--- /dev/null
+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;
<html>
<head>
- <title class="title">page title</title>
+ <title class="page title">page title</title>
<meta name="description" />
<meta name="keywords" />
</head>
<body>
- <div class="title">page title</div>
+ <div class="page title">page title</div>
<div>
<ul class="topbar_entries">
<li><a href="/">Home</a></li>
</ul>
<div>
<div class="Sidebar">
- <div class="sidebar_segment">
- <h4 class="sidebar_title"></h4>
- <ul class="sidebar_entries">
- <li><a class="entry"></a></li>
- </ul>
+ <div class="sidebar block">
+ <h4 class="sidebar title"></h4>
+ <div class="sidebar segment">
+ <h5 class="sidebar subtitle"></h5>
+ <ul class="sidebar entries">
+ <li><a class="entry title link"></a></li>
+ </ul>
+ </div>
</div>
</div>
<div class="main" />
use strictures 1;
use Test::More;
use SCSite::PageSet;
+use IO::All;
sub check_structure {
my ($s) = @_;
my $body = delete $s->{body};
like($body, qr/^\s+<p>Some markdown here.<\/p>\s+$/sm, 'Body correct');
delete @{$s}{grep /^_/, keys %$s};
+ delete $s->{path};
is_deeply($s,
{
created => '',
);
}
-my $ps = SCSite::PageSet->new(base_dir => 't/pages');
+my $ps = SCSite::PageSet->new(base_dir => io->dir('t/pages'));
my $test_html = q{<html>
<head>