basic page rendering
[scpubgit/SCS.git] / lib / SCSite / PageSet.pm
1 package SCSite::PageSet;
2
3 { package SCSite::Page; use Moo;
4   has $_ => (is => 'ro') for qw(title description keywords body);
5 }
6
7 use IO::All;
8 use Text::MultiMarkdown 'markdown';
9 use HTML::Zoom;
10 use Moo;
11
12 has base_dir => (is => 'ro', required => 1);
13
14 sub get {
15   my ($self, $spec) = @_;
16   $spec->{path} or die "path is required to get";
17   my ($dir, $file) = $spec->{path} =~ m{^(?:(.*)/)?([^/]+)$};
18   my $type;
19   my @poss = io->dir($self->base_dir)->${\sub {
20     my $io = shift;
21     defined($dir) ? $io->catdir($dir) : $io
22   }}->filter(sub { $_->filename =~ /\Q${file}\E\.(html|md)/ and $type = $1 })
23     ->all_files;
24   die "multiple files found for ${\$spec->{path}}:\n".join "\n", @poss
25     if @poss > 1;
26   $self->${\"_inflate_${type}"}($poss[0]->all);
27 }
28
29 sub _new_page {
30   SCSite::Page->new($_[1])
31 }
32
33 sub _inflate_html {
34   my ($self, $html) = @_;
35   $self->_new_page($self->_extract_from_html($html));
36 }
37
38 sub _extract_from_html {
39   my ($self, $html) = @_;
40   HTML::Zoom->from_html($html)
41     ->select('title')->collect_content({ into => \my @title })
42     ->select('meta[name=description]')->collect({ into => \my @description })
43     ->select('meta[name=keywords]')->collect({ into => \my @keywords })
44     ->select('body')->collect_content({ into => \my @body })
45     ->run;
46   +{
47     title => $title[0]->{raw},
48     description => $description[0]->{attrs}{content},
49     keywords => $keywords[0]->{attrs}{content},
50     body => HTML::Zoom->from_events(\@body)->to_html,
51   }
52 }
53
54 sub _inflate_md {
55   my ($self, $md) = @_;
56   $self->_new_page($self->_extract_from_md($md));
57 }
58
59 sub _extract_from_md {
60   my ($self, $md) = @_;
61   $self->_extract_from_html(markdown($md, { document_format => 'complete' }));
62 }
63
64 1;