package CPAN::Mini::Webserver::Templates;
use strict;
use warnings;
use Template::Declare::Tags;
use base 'Template::Declare';
private template 'header' => sub {
my ( $self, $title ) = @_;
head {
title {$title};
link {
attr {
rel => 'stylesheet',
href => '/static/css/screen.css',
type => 'text/css',
media => 'screen, projection'
}
};
link {
attr {
rel => 'stylesheet',
href => '/static/css/print.css',
type => 'text/css',
media => 'print'
}
};
outs_raw
'';
link {
attr {
rel => 'icon',
href => '/static/images/favicon.png',
type => 'image/png',
}
};
link {
attr {
rel => 'search',
href => '/static/xml/opensearch.xml',
type => 'application/opensearchdescription+xml',
title => 'minicpan search',
}
};
meta { attr { generator => 'CPAN::Mini::Webserver' } };
}
};
private template 'footer' => sub {
my $self = shift;
my $version = $CPAN::Mini::Webserver::VERSION;
div {
attr { id => "footer" };
small {
"Generated by CPAN::Mini::Webserver $version";
};
}
};
private template 'author_link' => sub {
my ( $self, $author ) = @_;
a {
attr { href => '/~' . lc( $author->pauseid ) . '/' };
$author->name;
};
};
private template 'distribution_link' => sub {
my ( $self, $distribution ) = @_;
a {
attr { href => '/~'
. lc( $distribution->cpanid ) . '/'
. $distribution->distvname
. '/' };
$distribution->distvname;
};
};
private template 'package_link' => sub {
my ( $self, $package ) = @_;
my $distribution = $package->distribution;
a {
attr { href => '/package/'
. lc( $distribution->cpanid ) . '/'
. $distribution->distvname . '/'
. $package->package
. '/' };
$package->package;
};
};
private template distribution_file => sub {
my ( $self, $pauseid, $distvname, $filename ) = (@_);
my $display_filename
= ( $filename =~ /^$distvname\/(.*)$/ )
? $1
: $filename;
my $href
= ( $filename =~ /\.(pm|pod)$/ )
? "/~$pauseid/$distvname/$filename"
: "/raw/~$pauseid/$distvname/$filename";
row {
cell {
a {
attr { href => $href };
span {
$display_filename;
};
};
};
};
};
private template 'searchbar' => sub {
my $self = shift;
my $q = shift;
table {
row {
form {
attr { name => 'f', method => 'get', action => '/search/' };
cell {
attr { class => 'searchbar' };
outs_raw
q|
|;
};
cell {
attr { class => 'searchbar' };
input {
{ attr { type => 'text', name => 'q', value => $q } };
};
input {
{
attr {
type => 'submit',
value => 'Search Mini CPAN'
}
};
};
};
};
};
};
};
private template 'search_results' => sub {
my ( $self, $arguments ) = @_;
my $parse_cpan_authors = $arguments->{parse_cpan_authors};
my $q = $arguments->{q};
my @authors = @{ $arguments->{authors} };
my @distributions = @{ $arguments->{distributions} };
my @packages = @{ $arguments->{packages} };
if ( @authors + @distributions + @packages ) {
outs_raw '
';
foreach my $author (@authors) {
row {
cell {
show( 'author_link', $author );
};
};
}
foreach my $distribution (@distributions) {
row {
cell {
show( 'distribution_link', $distribution );
outs ' by ';
show( 'author_link',
$parse_cpan_authors->author( $distribution->cpanid )
);
};
};
}
foreach my $package (@packages) {
row {
cell {
show( 'package_link', $package );
outs ' by ';
show(
'author_link',
$parse_cpan_authors->author(
$package->distribution->cpanid
)
);
};
};
}
outs_raw '
';
} else {
p {'No results found.'};
}
};
template 'index' => sub {
my ( $self, $arguments ) = @_;
my $parse_cpan_authors = $arguments->{parse_cpan_authors};
my $recents = $arguments->{recents};
html {
attr { xmlns => 'http://www.w3.org/1999/xhtml' };
div {
attr { class => 'container' };
div {
attr { class => 'span-24' };
show( 'header', 'Index' );
body {
attr { onload => 'document.f.q.focus()' };
show('searchbar');
h1 {'Index'};
p {'Welcome to CPAN::Mini::Webserver. Start searching!'};
if ($recents) {
h2 {'Recent distributions'};
ul {
foreach my $recent (@$recents) {
my $cpanid = $recent->cpanid;
my $distvname = $recent->distvname;
next unless $distvname;
li {
a {
attr { href => '/~'
. lc($cpanid) . '/'
. $distvname };
$distvname;
};
outs ' by ';
show(
'author_link',
$parse_cpan_authors->author(
$cpanid
)
);
}
}
};
}
};
show('footer');
};
};
};
};
template '404' => sub {
my ( $self, $arguments ) = @_;
my $q = $arguments->{q};
html {
attr { xmlns => 'http://www.w3.org/1999/xhtml' };
div {
attr { class => 'container' };
div {
attr { class => 'span-24' };
show( 'header', 'File not found' );
body {
show( 'searchbar', $q );
h1 {'Sorry. I couldn\'t find the page you wanted.'};
p {
"Unfortunately, the page you were looking for doesn't exist. Perhaps a quick search for $q will turn up what you were looking for:";
};
};
h2 {
outs "Search for ";
outs_raw '';
outs $q;
outs_raw '';
};
show( 'search_results', $arguments );
show('footer');
};
};
};
};
template 'search' => sub {
my ( $self, $arguments ) = @_;
my $q = $arguments->{q};
html {
show( 'header', "Search for `$q'" );
body {
div {
attr { class => 'container' };
div {
attr { class => 'span-24' };
show( 'searchbar', $q );
h1 {
outs "Search for ";
outs_raw '';
outs $q;
outs_raw '';
};
show( 'search_results', $arguments );
show('footer');
}
};
}
};
};
private template 'authorinfo' => sub {
my ( $self, $author ) = @_;
my $pauseid = $author->pauseid;
my $email = $author->email;
my $url = $author->can('homepage') ? $author->homepage : undef;
my $prefix
= 'id' . '/'
. substr( $pauseid, 0, 1 ) . '/'
. substr( $pauseid, 0, 2 ) . '/'
. $pauseid;
h2 {"Links"};
ul {
li {
a {
attr { href => "http://backpan.perl.org/authors/$prefix" };
'BackPAN';
};
}
li {
a {
attr { href => "mailto:$email" };
$email;
};
}
li {
a {
attr { href => $url };
$url;
};
}
li {
a {
attr { href =>
"http://cpantesters.perl.org/author/$pauseid.html" };
'CPANTesters';
};
}
li {
a {
attr { href =>
"http://bbbike.radzeit.de/~slaven/cpantestersmatrix.cgi?author=$pauseid"
};
'Test Matrix';
};
}
}
};
template 'author' => sub {
my ( $self, $arguments ) = @_;
my $author = $arguments->{author};
my $pauseid = $arguments->{pauseid};
my $distvname = $arguments->{distvname};
my @distributions = @{ $arguments->{distributions} };
my $dates = $arguments->{dates};
html {
show( 'header', $author->name );
body {
div {
attr { class => 'container' };
div {
attr { class => 'span-24 last' };
show('searchbar');
h1 { show( 'author_link', $author ) };
}
div {
attr { class => 'span-18 last' };
outs_raw '';
foreach my $distribution (@distributions) {
row {
cell {
show( 'distribution_link', $distribution );
};
cell {
outs $dates->{ $distribution->distvname };
};
};
}
outs_raw '
';
}
div {
attr { class => 'span-6 last' };
show( 'authorinfo', $author );
};
div {
attr { class => 'span-24 last' };
show('footer');
};
};
};
}
};
private template 'dependencies' => sub {
my ( $self, $meta, $pcp ) = @_;
div {
attr { class => 'dependencies' };
h2 {'Dependencies'};
ul {
foreach
my $deptype (qw(requires build_requires configure_requires))
{
if ( defined $meta->{$deptype} ) {
foreach my $package ( sort keys %{ $meta->{$deptype} } ) {
next if $package eq 'perl';
my $d = $pcp->package($package)->distribution;
next unless $d;
my $distvname = $d->distvname;
my $author = $d->cpanid;
li {
a {
attr { href => "/~$author/$distvname/" };
$package;
};
if ( $deptype =~ /(.*?)_/ ) {
outs " ($1 requirement)";
}
}
}
}
}
}
}
};
private template 'metadata' => sub {
my ( $self, $meta ) = @_;
h2 {'Metadata'};
div {
attr { class => 'metadata' };
dl {
foreach
my $key ( qw(abstract license repository), 'release date' )
{
if ( defined $meta->{$key} ) {
dt { ucfirst $key; };
if ( defined $meta->{resources}->{$key} ) {
a {
attr {
href => delete $meta->{resources}->{$key} };
$meta->{$key};
};
} else {
dd { $meta->{$key} };
}
}
}
foreach my $datum ( keys %{ $meta->{resources} } ) {
dt { ucfirst $datum; }
dd {
a {
attr { href => $meta->{resources}->{$datum}; };
$meta->{resources}->{$datum};
}
}
}
}
};
};
private template 'download' => sub {
my ( $self, $author, $distribution ) = @_;
my $distvname = $distribution->distvname;
h2 {'Download'};
div {
a {
attr { href => '/download/~' . $author->pauseid . "/$distvname" };
$distribution->filename;
}
};
};
private template 'install' => sub {
my ( $self, $author, $distribution, $filenames ) = @_;
my $distvname = $distribution->distvname;
# Check whether we have the module/distribution installed
# And display the status
# Just fudge:
# * If we have lib/*.pm, that's a contained module
my @modules = map {
m![^/]*/lib/(.*?)\.pm!;
$_ = $1;
s!/!::!g;
$_
} grep {
m![^/]*/lib/.*?\.pm$!
} @{$filenames};
my $installed_version = Module::InstalledVersion->new( $modules[0] );
my $msg = "Not installed on this Perl";
my $action = 'Install';
if ( $installed_version->{version} ) {
$msg = sprintf 'You have version %s installed.',
$installed_version->{version};
if ( $installed_version->{version} lt $distribution->version ) {
$action = 'Update';
} elsif ( $installed_version->{version} eq $distribution->version ) {
$action = 'Reinstall';
} else {
$action = 'Downgrade';
}
}
h2 {'Install'};
div {
attr { class => 'install' };
div { attr { 'class' => "install-message" }; $msg };
form {
attr { class => 'install-link' } attr { method => 'PUT' };
attr {
action => '/install/~'
. lc( $distribution->cpanid ) . '/'
. $distribution->distvname . '/'
. $distribution->filename;
};
button {$action} $action;
};
};
};
private template 'dist_links' => sub {
my ( $self, $distribution ) = @_;
my $distname = $distribution->dist;
h2 {'Links'};
ul {
li {
outs "Test ";
a {
attr { href =>
"http://bbbike.radzeit.de/~slaven/cpantestersmatrix.cgi?dist=$distname"
};
"matrix";
};
outs " and ";
a {
attr { href =>
"http://cpantesters.perl.org/show/$distname.html" };
"reports";
};
}
li {
a {
attr { href =>
"http://rt.cpan.org/NoAuth/Bugs.html?Dist=$distname"
};
"RT";
};
outs " (or via ";
a {
attr { href => "mailto:bug-$distname\@rt.cpan.org" } "email";
};
outs ")";
}
li {
a {
attr { href => "http://annocpan.org/dist/$distname" };
"AnnoCPAN";
}
}
li {
a {
attr { href => "http://cpanratings.perl.org/d/$distname" };
"CPAN Ratings";
}
}
}
};
template 'filelist' => sub {
my ( $self, $pauseid, $distvname, $label, $filenames ) = @_;
h2 {$label};
outs_raw '';
foreach my $filename (@$filenames) {
show(
distribution_file => $pauseid,
$distvname, $filename
);
}
outs_raw '
';
};
template 'distribution' => sub {
my ( $self, $arguments ) = @_;
my $author = $arguments->{author};
my $pauseid = $arguments->{pauseid};
my $distvname = $arguments->{distvname};
my $distribution = $arguments->{distribution};
my @filenames = @{ $arguments->{filenames} };
my $meta = $arguments->{meta};
my $pcp = $arguments->{pcp};
html {
show( 'header', $author->name . ' > ' . $distvname );
body {
div {
attr { class => 'container' };
div {
attr { class => 'span-24 last' };
show('searchbar');
h1 {
show( 'author_link', $author );
outs ' > ';
show( 'distribution_link', $distribution );
};
}
div {
attr { class => 'span-18 last' };
# outs_raw '';
my ( @code, @test, @other, @doc );
foreach (@filenames) {
if ( m{(?:/bin/|\.p(?:m|l)$)} and not m{/inc/} ) {
push @code, $_;
} elsif (m{\.pod$}) {
push @doc, $_;
} elsif (/\.t$/) {
push @test, $_;
} else {
push @other, $_;
}
}
show( 'filelist', $pauseid, $distvname, 'Code', \@code )
if @code;
show( 'filelist', $pauseid, $distvname, 'Documentation',
\@doc )
if @doc;
show( 'filelist', $pauseid, $distvname, 'Tests', \@test )
if @test;
show( 'filelist', $pauseid, $distvname, 'Other', \@other )
if @other;
# foreach my $filename (@filenames) {
# show(
# distribution_file => $pauseid,
# $distvname, $filename
# );
# }
# outs_raw '
';
};
div {
attr { class => 'span-6 last' };
show( 'metadata', $meta );
show( 'dependencies', $meta, $pcp );
show( 'download', $author, $distribution );
show( 'install', $author, $distribution, \@filenames );
show( 'dist_links', $distribution );
};
div {
attr { class => 'span-24 last' };
show('footer');
};
}
};
}
};
template 'file' => sub {
my ( $self, $arguments ) = @_;
my $author = $arguments->{author};
my $distribution = $arguments->{distribution};
my $filename = $arguments->{filename};
my $pauseid = $arguments->{pauseid};
my $distvname = $arguments->{distvname};
my $file = $arguments->{filename};
my $contents = $arguments->{contents};
my $html = $arguments->{html};
html {
show( 'header',
$author->name . ' > ' . $distvname . ' > ' . $filename );
body {
div {
attr { class => 'container' };
div {
attr { class => 'span-24' };
show('searchbar');
h1 {
show( 'author_link', $author );
outs ' > ';
show( 'distribution_link', $distribution );
outs ' > ';
outs $filename;
};
a {
attr {
href => "/raw/~$pauseid/$distvname/$filename" };
"See raw file";
};
if ($html) {
div {
attr { id => "pod" };
outs_raw $html;
};
} else {
pre {$contents};
}
show('footer');
};
};
};
}
};
template 'raw' => sub {
my ( $self, $arguments ) = @_;
my $author = $arguments->{author};
my $distribution = $arguments->{distribution};
my $filename = $arguments->{filename};
my $pauseid = $arguments->{pauseid};
my $distvname = $arguments->{distvname};
my $contents = $arguments->{contents};
my $html = $arguments->{html};
html {
show( 'header',
$author->name . ' > ' . $distvname . ' > ' . $filename );
body {
div {
attr { class => 'container' };
div {
attr { class => 'span-24' };
show('searchbar');
h1 {
show( 'author_link', $author );
outs ' > ';
show( 'distribution_link', $distribution );
outs ' > ';
outs $filename;
};
if ($html) {
div {
attr { id => "code" };
code {
outs_raw $html;
};
};
} else {
pre {$contents};
}
div {
attr { class => 'download-link' };
a {
attr { href => '/download/~'
. $author->pauseid
. "/$distvname/$filename" };
"Download as plain text";
};
};
show('footer');
};
};
};
}
};
template 'opensearch' => sub {
my $self = shift;
outs_raw q|
minicpan_webserver
Search minicpan
UTF-8
data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%03%00%00%00(-%0FS%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%003PLTE8%00%00%05%08%04%16%18%15%1E%1F%1D!%22%20%26(%26%2C-%2B130%3B%3D%3AFHELMKXZWegdxyw%84%86%83%9E%A0%9D%CC%CE%CBjq%F6r%00%00%00%01tRNS%00%40%E6%D8f%00%00%00lIDAT%18%D3u%8FY%0E%C20%0C%05%BD%AF)%ED%FDO%0B%85%10%15%04%EF%C7%1A%7B%2C%D9%00%7Fr%C4W%A3u%EB%2B%EFn%E3sAnr1%8E%E11%D4rq%1Bn%9E%CC%8B%15%C5%01%14u%B2%A0%3EmA9K1Z%BD%5C%C6%87%18%B4%18%8A0%A0Q%2B%C3%CC%232%9D%CE%19%E1%3B%3C%E6%E6%CA%BC%C4%A5%BB%C2%84%FC%D7%DBw%7BS%02%E3Ki%23G%00%00%00%00IEND%AEB%60%82
|;
};
__END__
=head1 NAME
CPAN::Mini::Webserver::Templates - Templates for CPAN::Mini::Webserver
=head1 DESCRIPTION
This module holds the templates, CSS and images for
CPAN::Mini::Webserver.
=head1 AUTHOR
Leon Brocard
=head1 COPYRIGHT
Copyright (C) 2008, Leon Brocard.
This module is free software; you can redistribute it or
modify it under the same terms as Perl itself.