Merge branch 'fancypodcast' of github.com:schmonz/ikiwiki into fancypodcast

master
Amitai Schlair 2013-02-20 21:59:55 -05:00
commit cdae4fe6ec
6 changed files with 161 additions and 40 deletions

View File

@ -611,6 +611,26 @@ sub absolute_urls ($$) {
return $ret; return $ret;
} }
sub genenclosure {
my $itemtemplate=shift;
my $url=shift;
my $file=shift;
return unless $itemtemplate->query(name => "enclosure");
my $size=(srcfile_stat($file))[8];
my $mime="unknown";
eval q{use File::MimeInfo};
if (! $@) {
$mime = mimetype($file);
}
$itemtemplate->param(
enclosure => $url,
type => $mime,
length => $size,
);
}
sub genfeed ($$$$$@) { sub genfeed ($$$$$@) {
my $feedtype=shift; my $feedtype=shift;
my $feedurl=shift; my $feedurl=shift;
@ -627,6 +647,7 @@ sub genfeed ($$$$$@) {
foreach my $p (@pages) { foreach my $p (@pages) {
my $u=URI->new(encode_utf8(urlto($p, "", 1))); my $u=URI->new(encode_utf8(urlto($p, "", 1)));
my $pcontent = absolute_urls(get_inline_content($p, $page), $url); my $pcontent = absolute_urls(get_inline_content($p, $page), $url);
my $fancy_enclosure_seen = 0;
$itemtemplate->param( $itemtemplate->param(
title => pagetitle(basename($p)), title => pagetitle(basename($p)),
@ -648,32 +669,27 @@ sub genfeed ($$$$$@) {
$itemtemplate->param(mdate_822 => date_822($pagestate{$p}{meta}{updated})); $itemtemplate->param(mdate_822 => date_822($pagestate{$p}{meta}{updated}));
$itemtemplate->param(mdate_3339 => date_3339($pagestate{$p}{meta}{updated})); $itemtemplate->param(mdate_3339 => date_3339($pagestate{$p}{meta}{updated}));
} }
if (exists $pagestate{$p}{meta}{enclosure}) {
my $absurl = $pagestate{$p}{meta}{enclosure};
# XXX better way to compute relative to srcdir?
my $file = $absurl;
$file =~ s|^$config{url}/||;
genenclosure($itemtemplate, $absurl, $file);
$fancy_enclosure_seen = 1;
}
} }
if ($itemtemplate->query(name => "enclosure")) { my $file=$pagesources{$p};
my $file=$pagesources{$p}; unless ($fancy_enclosure_seen || defined(pagetype($file))) {
my $type=pagetype($file); genenclosure($itemtemplate, $u, $file);
if (defined $type) { $itemtemplate->param(simplepodcast => 1);
$itemtemplate->param(content => $pcontent);
}
else {
my $size=(srcfile_stat($file))[8];
my $mime="unknown";
eval q{use File::MimeInfo};
if (! $@) {
$mime = mimetype($file);
}
$itemtemplate->param(
enclosure => $u,
type => $mime,
length => $size,
);
}
}
else {
$itemtemplate->param(content => $pcontent);
} }
$itemtemplate->param(content => $pcontent);
run_hooks(pagetemplate => sub { run_hooks(pagetemplate => sub {
shift->(page => $p, destpage => $page, shift->(page => $p, destpage => $page,
template => $itemtemplate); template => $itemtemplate);

View File

@ -128,7 +128,7 @@ sub preprocess (@) {
} }
add_depends($page, $link, deptype("presence")); add_depends($page, $link, deptype("presence"));
$value=urlto($link, $page); $value=urlto($link, $page, 1);
$pagestate{$page}{meta}{enclosure}=$value; $pagestate{$page}{meta}{enclosure}=$value;
# fallthrough # fallthrough
} }
@ -330,7 +330,7 @@ sub pagetemplate (@) {
} }
if (exists $pagestate{$page}{meta}{enclosure}) { if (exists $pagestate{$page}{meta}{enclosure}) {
$template->param(enclosure => $pagestate{$page}{meta}{enclosure}); $template->param(enclosure => HTML::Entities::encode_entities(IkiWiki::urlabs($pagestate{$page}{meta}{enclosure}, $config{url})));
} }
foreach my $field (qw{authorurl}) { foreach my $field (qw{authorurl}) {

View File

@ -30,12 +30,12 @@ also have lots more metadata.
* Write failing tests for the desired single-page and inlined * Write failing tests for the desired single-page and inlined
HTML behavior, then make them pass by adding enclosure stanzas HTML behavior, then make them pass by adding enclosure stanzas
to `{,inline}page.tmpl`. to `{,inline}page.tmpl`.
### Must-have (for [[schmonz]], anyway)
* Write failing tests for the desired RSS/Atom behavior, then make * Write failing tests for the desired RSS/Atom behavior, then make
them pass, probably via changes to `{atom,rss}item.tmpl` and them pass, probably via changes to `{atom,rss}item.tmpl` and
[[plugins/inline]]. [[plugins/inline]].
### Must-have (for [[schmonz]], anyway)
* Enrich podcast feed metadata (some of which is iTunes-specific, * Enrich podcast feed metadata (some of which is iTunes-specific,
though I'm not aware of it causing any problems for other though I'm not aware of it causing any problems for other
podcatchers, and in fact some of them may also use it). podcatchers, and in fact some of them may also use it).

View File

@ -9,7 +9,7 @@ BEGIN {
"XML::Feed and/or HTML::Parser not available"}; "XML::Feed and/or HTML::Parser not available"};
} }
else { else {
eval q{use Test::More tests => 89}; eval q{use Test::More tests => 136};
} }
} }
@ -72,6 +72,11 @@ sub simple_podcast {
qq{$format $title id}); qq{$format $title id});
is($body, undef, is($body, undef,
qq{$format $title no body text}); qq{$format $title no body text});
# prevent undef method killing test harness
$enclosure = XML::Feed::Enclosure->new({})
unless defined $enclosure;
is($enclosure->url, $url, is($enclosure->url, $url,
qq{$format $title enclosure url}); qq{$format $title enclosure url});
is($enclosure->type, $media_types{$title}, is($enclosure->type, $media_types{$title},
@ -93,6 +98,90 @@ sub simple_podcast {
ok(! system("rm -rf $tmp $statedir"), q{teardown}); ok(! system("rm -rf $tmp $statedir"), q{teardown});
} }
sub fancy_podcast {
my $baseurl = 'http://example.com';
my @command = (qw(./ikiwiki.out -plugin inline -rss -atom));
push @command, qw(-underlaydir=underlays/basewiki);
push @command, qw(-set underlaydirbase=underlays -templatedir=templates);
push @command, "-url=$baseurl", qw(t/tinypodcast), "$tmp/out";
ok(! system("mkdir $tmp"),
q{setup});
ok(! system(@command),
q{build});
my %media_types = (
'piano.mp3' => 'audio/mpeg',
'walter.ogg' => 'video/x-theora+ogg',
);
for my $format (qw(atom rss)) {
my $feed = XML::Feed->parse("$tmp/out/fancy/index.$format");
is($feed->title, 'fancy',
qq{$format feed title});
is($feed->link, "$baseurl/fancy/",
qq{$format feed link});
is($feed->description, 'wiki',
qq{$format feed description});
if ('atom' eq $format) {
is($feed->author, $feed->description,
qq{$format feed author});
is($feed->id, $feed->link,
qq{$format feed id});
is($feed->generator, "ikiwiki",
qq{$format feed generator});
}
# XXX compare against simple_podcast
# XXX make them table-driven shared code
for my $entry ($feed->entries) {
my $title = $entry->title;
my $url = $entry->id;
my $body = $entry->content->body;
my $enclosure = $entry->enclosure;
is($entry->link, $url, qq{$format $title link});
isnt($entry->issued, undef,
qq{$format $title issued date});
isnt($entry->modified, undef,
qq{$format $title modified date});
if (defined $media_types{$title}) {
is($url, "$baseurl/$title",
qq{$format $title id});
is($body, undef,
qq{$format $title no body text});
is($enclosure->url, $url,
qq{$format $title enclosure url});
is($enclosure->type, $media_types{$title},
qq{$format $title enclosure type});
cmp_ok($enclosure->length, '>', 0,
qq{$format $title enclosure length});
}
else {
my $expected_id = "$baseurl/$title/";
$expected_id =~ s/\ /_/g;
is($url, $expected_id,
qq{$format $title id});
isnt($body, undef,
qq{$format $title body text});
isnt($enclosure, undef,
qq{$format $title enclosure});
use File::Basename;
my $filename = basename($enclosure->url);
is($enclosure->type, $media_types{$filename},
qq{$format $title enclosure type});
cmp_ok($enclosure->length, '>', 0,
qq{$format $title enclosure length});
}
}
}
ok(! system("rm -rf $tmp $statedir"), q{teardown});
}
sub single_page_html { sub single_page_html {
my @command = (qw(./ikiwiki.out)); my @command = (qw(./ikiwiki.out));
push @command, qw(-underlaydir=underlays/basewiki); push @command, qw(-underlaydir=underlays/basewiki);
@ -110,8 +199,8 @@ sub single_page_html {
like(_extract_html_content($html, 'enclosure'), qr/this episode/m, like(_extract_html_content($html, 'enclosure'), qr/this episode/m,
q{html enclosure}); q{html enclosure});
my ($href) = _extract_html_links($html, 'piano'); my ($href) = _extract_html_links($html, 'piano');
ok(-f $href, is($href, '/piano.mp3',
q{html enclosure exists}); q{html enclosure sans -url is site-absolute});
$html = "$tmp/out/attempted_multiple_enclosures/index.html"; $html = "$tmp/out/attempted_multiple_enclosures/index.html";
like(_extract_html_content($html, 'content'), qr/has content and/m, like(_extract_html_content($html, 'content'), qr/has content and/m,
@ -119,8 +208,21 @@ sub single_page_html {
like(_extract_html_content($html, 'enclosure'), qr/this episode/m, like(_extract_html_content($html, 'enclosure'), qr/this episode/m,
q{html enclosure}); q{html enclosure});
($href) = _extract_html_links($html, 'walter'); ($href) = _extract_html_links($html, 'walter');
ok(-f $href, is($href, '/walter.ogg',
q{html enclosure exists}); q{html enclosure sans -url is site-absolute});
my $baseurl = 'http://example.com';
ok(! system(@command, "-url=$baseurl", q{--rebuild}));
$html = "$tmp/out/pianopost/index.html";
($href) = _extract_html_links($html, 'piano');
is($href, "$baseurl/piano.mp3",
q{html enclosure with -url is fully absolute});
$html = "$tmp/out/attempted_multiple_enclosures/index.html";
($href) = _extract_html_links($html, 'walter');
is($href, "$baseurl/walter.ogg",
q{html enclosure with -url is fully absolute});
ok(! system("rm -rf $tmp $statedir"), q{teardown}); ok(! system("rm -rf $tmp $statedir"), q{teardown});
} }
@ -146,11 +248,11 @@ sub inlined_pages_html {
like($enclosures, qr/this episode/m, like($enclosures, qr/this episode/m,
q{html enclosure}); q{html enclosure});
my ($href) = _extract_html_links($html, 'piano.mp3'); my ($href) = _extract_html_links($html, 'piano.mp3');
ok(-f $href, is($href, '/piano.mp3',
q{html enclosure from pianopost exists}); q{html enclosure from pianopost sans -url});
($href) = _extract_html_links($html, 'walter.ogg'); ($href) = _extract_html_links($html, 'walter.ogg');
ok(-f $href, is($href, '/walter.ogg',
q{html enclosure from attempted_multiple_enclosures exists}); q{html enclosure from attempted_multiple_enclosures sans -url});
ok(! system("rm -rf $tmp $statedir"), q{teardown}); ok(! system("rm -rf $tmp $statedir"), q{teardown});
} }
@ -198,3 +300,4 @@ sub _extract_html_links {
simple_podcast(); simple_podcast();
single_page_html(); single_page_html();
inlined_pages_html(); inlined_pages_html();
fancy_podcast();

View File

@ -34,11 +34,12 @@
<published><TMPL_VAR CDATE_3339></published> <published><TMPL_VAR CDATE_3339></published>
<TMPL_IF ENCLOSURE> <TMPL_IF ENCLOSURE>
<link rel="enclosure" type="<TMPL_VAR TYPE>" href="<TMPL_VAR ENCLOSURE>" length="<TMPL_VAR LENGTH>" /> <link rel="enclosure" type="<TMPL_VAR TYPE>" href="<TMPL_VAR ENCLOSURE>" length="<TMPL_VAR LENGTH>" />
<TMPL_ELSE> </TMPL_IF>
<TMPL_UNLESS SIMPLEPODCAST>
<content type="html" xml:lang="en"> <content type="html" xml:lang="en">
<TMPL_VAR CONTENT ESCAPE=HTML> <TMPL_VAR CONTENT ESCAPE=HTML>
</content> </content>
</TMPL_IF> </TMPL_UNLESS>
<TMPL_IF COMMENTSURL> <TMPL_IF COMMENTSURL>
<link rel="comments" href="<TMPL_VAR COMMENTSURL>" type="text/html" /> <link rel="comments" href="<TMPL_VAR COMMENTSURL>" type="text/html" />
</TMPL_IF> </TMPL_IF>

View File

@ -20,9 +20,10 @@
<dcterms:modified><TMPL_VAR MDATE_3339></dcterms:modified> <dcterms:modified><TMPL_VAR MDATE_3339></dcterms:modified>
<TMPL_IF ENCLOSURE> <TMPL_IF ENCLOSURE>
<enclosure url="<TMPL_VAR ENCLOSURE>" type="<TMPL_VAR TYPE>" length="<TMPL_VAR LENGTH>" /> <enclosure url="<TMPL_VAR ENCLOSURE>" type="<TMPL_VAR TYPE>" length="<TMPL_VAR LENGTH>" />
<TMPL_ELSE>
<description><TMPL_VAR CONTENT ESCAPE=HTML></description>
</TMPL_IF> </TMPL_IF>
<TMPL_UNLESS SIMPLEPODCAST>
<description><TMPL_VAR CONTENT ESCAPE=HTML></description>
</TMPL_UNLESS>
<TMPL_IF COMMENTSURL> <TMPL_IF COMMENTSURL>
<comments><TMPL_VAR COMMENTSURL></comments> <comments><TMPL_VAR COMMENTSURL></comments>
</TMPL_IF> </TMPL_IF>