--- /dev/null
+package SCSite::PageSet;
+
+{ package SCSite::Page; use Moo;
+ has $_ => (is => 'ro') for qw(title description keywords body);
+}
+
+use IO::All;
+use Text::MultiMarkdown 'markdown';
+use HTML::Zoom;
+use Moo;
+
+has base_dir => (is => 'ro', required => 1);
+
+sub get {
+ my ($self, $spec) = @_;
+ $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 $io = shift;
+ defined($dir) ? $io->catdir($dir) : $io
+ }}->filter(sub { $_->filename =~ /\Q${file}\E\.(html|md)/ and $type = $1 })
+ ->all_files;
+ die "multiple files found for ${\$spec->{path}}:\n".join "\n", @poss
+ if @poss > 1;
+ $self->${\"_inflate_${type}"}($poss[0]->all);
+}
+
+sub _new_page {
+ SCSite::Page->new($_[1])
+}
+
+sub _inflate_html {
+ my ($self, $html) = @_;
+ $self->_new_page($self->_extract_from_html($html));
+}
+
+sub _extract_from_html {
+ my ($self, $html) = @_;
+ HTML::Zoom->from_html($html)
+ ->select('title')->collect_content({ into => \my @title })
+ ->select('meta[name=description]')->collect({ into => \my @description })
+ ->select('meta[name=keywords]')->collect({ into => \my @keywords })
+ ->select('body')->collect_content({ into => \my @body })
+ ->run;
+ +{
+ title => $title[0]->{raw},
+ description => $description[0]->{attrs}{content},
+ keywords => $keywords[0]->{attrs}{content},
+ body => HTML::Zoom->from_events(\@body)->to_html,
+ }
+}
+
+sub _inflate_md {
+ my ($self, $md) = @_;
+ $self->_new_page($self->_extract_from_md($md));
+}
+
+sub _extract_from_md {
+ my ($self, $md) = @_;
+ $self->_extract_from_html(markdown($md, { document_format => 'complete' }));
+}
+
+1;
--- /dev/null
+use strictures 1;
+use Test::More;
+use SCSite::PageSet;
+
+sub check_structure {
+ my ($s) = @_;
+ $s = { %$s };
+ my $body = delete $s->{body};
+ like($body, qr/^\s+<p>Some markdown here.<\/p>\s+$/sm, 'Body correct');
+ is_deeply($s,
+ {
+ title => '--TITLE--',
+ description => '--DESCRIPTION--',
+ keywords => '--KW1-- --KW2--'
+ },
+ 'Metadata ok'
+ );
+}
+
+my $ps = SCSite::PageSet->new(base_dir => 't/pages');
+
+my $test_html = q{<html>
+ <head>
+ <title>--TITLE--</title>
+ <meta name="description" content="--DESCRIPTION--" />
+ <meta name="keywords" content="--KW1-- --KW2--" />
+ </head>
+ <body>
+ <p>Some markdown here.</p>
+ </body>
+</html>};
+
+check_structure($ps->_extract_from_html($test_html));
+
+my $test_md = q{Title: --TITLE--
+description: --DESCRIPTION--
+keywords: --KW1-- --KW2--
+
+Some markdown here.
+};
+
+check_structure($ps->_extract_from_md($test_md));
+
+check_structure($ps->get({ path => 'index' }));
+
+check_structure($ps->get({ path => 'one/two' }));
+
+done_testing;