Skip to content

Commit 93e598f

Browse files
authored
Merge pull request #16 from perl-users-jp/atom-feed
add feed.atom
2 parents 6c29eb4 + 2d9d65c commit 93e598f

File tree

3 files changed

+101
-11
lines changed

3 files changed

+101
-11
lines changed

cpanfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ requires 'Class::Tiny';
77
requires 'Date::Format';
88
requires 'Path::Tiny';
99
requires 'Text::MicroTemplate';
10+
requires 'XML::Atom';
1011

1112
requires 'Text::Xatena';
1213
requires 'Text::Markdown';

lib/PerlUsersJP/Builder.pm

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use Path::Tiny ();
1313
use Date::Format ();
1414
use Scalar::Util ();
1515
use Text::MicroTemplate;
16+
use XML::Atom::Feed;
17+
use XML::Atom::Entry;
18+
use XML::Atom::Person;
19+
use XML::Atom::Link;
1620

1721
use Text::Xatena;
1822
use Text::Xatena::Inline;
@@ -78,7 +82,7 @@ sub build_entries {
7882
$self->build_categories($src_list);
7983
$self->build_tags($src_list);
8084
#$self->build_sitemap(\@entries);
81-
#$self->build_atom(\@entries);
85+
$self->build_atom_feed($src_list);
8286
}
8387

8488

@@ -129,6 +133,22 @@ sub build_entry {
129133
$self->diag("Created entry $dest\n");
130134
}
131135

136+
# content/foo/bar.txt => /foo/bar
137+
sub entry_url_path {
138+
my ($self, $src) = @_;
139+
140+
my $content_dir = $self->content_dir;
141+
my $path = "$src";
142+
$path =~ s!$content_dir!!;
143+
$path =~ s!\.([^.]+)$!!;
144+
return $path;
145+
}
146+
147+
sub entry_url {
148+
my ($self, $src) = @_;
149+
return "https://perl-users.jp" . $self->entry_url_path($src);
150+
}
151+
132152
sub entry_text {
133153
my ($self, $src) = @_;
134154
my $matter = $self->front_matter($src);
@@ -281,14 +301,8 @@ sub build_tag {
281301
my $file = Path::Tiny::path($_);
282302
my $matter = $self->front_matter($file);
283303
my $title = $matter->title;
304+
my $href = $self->entry_url_path($file);
284305

285-
# content/foo/bar.txt => /foo/bar
286-
my $href = do {
287-
my $content_dir = $self->content_dir;
288-
my $path = $file =~ s!$content_dir!!r;
289-
my $href = $path =~ s!\.([^.]+)$!!r;
290-
$href;
291-
};
292306
{
293307
file => $file,
294308
matter => $matter,
@@ -316,9 +330,71 @@ sub build_sitemap {
316330
... # TODO
317331
}
318332

319-
sub build_atom {
320-
my ($self, $entries) = @_;
321-
... # TODO
333+
my $ATOM_FEED_COUNT = 10;
334+
my $ATOM_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S%z';
335+
336+
sub build_atom_feed {
337+
my ($self, $src_list) = @_;
338+
339+
my $feed = XML::Atom::Feed->new;
340+
$feed->title('新着記事 - Perl Users JP');
341+
$feed->id('tag:perl-users.jp,2020:/feed');
342+
$feed->lang('ja-JP');
343+
344+
{ # link alternate
345+
my $link = XML::Atom::Link->new;
346+
$link->type('text/html');
347+
$link->rel('alternate');
348+
$link->href('https://perl-users.jp');
349+
$feed->add_link($link);
350+
}
351+
352+
{ # link self
353+
my $link = XML::Atom::Link->new;
354+
$link->type('application/atom+xml');
355+
$link->rel('self');
356+
$link->href('https://perl-users.jp/feed.atom');
357+
$feed->add_link($link);
358+
}
359+
360+
my @sorted = sort { $b->stat->mtime <=> $a->stat->mtime } $src_list->@*;
361+
my @new_src_list = splice @sorted, 0, $ATOM_FEED_COUNT;
362+
for my $src (@new_src_list) {
363+
my $entry = XML::Atom::Entry->new;
364+
365+
my $matter = $self->front_matter($src);
366+
my $path = $self->entry_url_path($src);
367+
368+
$entry->title($matter->title);
369+
$entry->id("tag:perl-users.jp,2020:$path");
370+
$entry->updated(Date::Format::time2str($ATOM_DATE_FORMAT, $src->stat->mtime));
371+
#$entry->published(Date::Format::time2str($ATOM_DATE_FORMAT, $src->stat->mtime)); # FIXME mtime
372+
$entry->content(
373+
$self->entry_text($src)
374+
);
375+
376+
my $author = XML::Atom::Person->new;
377+
$author->name($matter->author);
378+
$entry->author($author);
379+
380+
my $link = XML::Atom::Link->new;
381+
$link->type('text/html');
382+
$link->rel('alternate');
383+
$link->href($self->entry_url($src));
384+
385+
$feed->add_entry($entry);
386+
}
387+
388+
my $first_src = $new_src_list[0];
389+
$feed->updated(Date::Format::time2str($ATOM_DATE_FORMAT, $first_src->stat->mtime));
390+
391+
my $xml = $feed->as_xml;
392+
393+
my $atom_dir = $self->public_dir->child();
394+
my $dest = $atom_dir->child('feed.atom');
395+
$atom_dir->mkpath unless $atom_dir->is_dir;
396+
$dest->spew($xml);
397+
$self->diag("Created atom $dest\n");
322398
}
323399

324400
sub diag {
@@ -382,6 +458,9 @@ sub format_text {
382458
$parser->html_footer('');
383459
$parser->parse_string_document("=pod\n\n$text");
384460
}
461+
elsif ($format eq 'html') {
462+
return $text;
463+
}
385464
else {
386465
die "unsupported format: $format";
387466
}

script/app.psgi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,15 @@ builder {
66
s!/([^\.]+)$!/$1/!;
77
s!(.*/$)!$1/index.html! or return qr{^/.+};
88
},
9+
content_type => sub {
10+
my $file = shift;
11+
my $content_type = Plack::MIME->mime_type($file) || 'text/plain';
12+
13+
if ($content_type eq 'application/atom+xml') {
14+
$content_type .= "; charset=utf-8";
15+
}
16+
17+
return $content_type;
18+
},
919
root => './public/';
1020
};

0 commit comments

Comments
 (0)