use strictures 1;
package Mojito::Model::MetaCPAN;
$Mojito::Model::MetaCPAN::VERSION = '0.25';
use Moo;
use HTTP::Tiny;
use MetaCPAN::API;
use Text::MultiMarkdown;
use CHI;
use Data::Dumper::Concise;
=head1 Name
Mojito::Model::MetaCPAN - Tap into metacpan.org
=cut
has http_client => (
is => 'ro',
lazy => 1,
default => sub { HTTP::Tiny->new },
);
has metacpan => (
is => 'ro',
lazy => 1,
default => sub { MetaCPAN::API->new },
);
has cache => (
is => 'rw',
default => sub {
CHI->new(
driver => 'Memory',
global => 1,
# driver => 'File',
root_dir => '/tmp/mojito/cache',
);
},
);
has not_found_string => (
is => 'rw',
lazy => 1,
'default' => sub { 'NOT FOUND' },
);
has markdown => (
is => 'ro',
lazy => 1,
'default' => sub { return Text::MultiMarkdown->new }
);
=head1 Methods
=head2 get_synopsis_from_metacpan
Args: (Str: main module path, ModuleName: main module)
Returns: (Array: ($pod_url_used, @synopsis_lines)
=cut
sub get_synopsis_from_metacpan {
my ($self, $main_module, $pod_url) = @_;
my $pod_url_used = 'release';
# Use markdown format (easy to parse out SYNOPSIS)
# my $format = '?content-type=text/x-markdown';
my $format = '?content-type=text/plain';
my $secondary_pod_url = "https://fastapi.metacpan.org/pod/${main_module}${format}";
if (not $pod_url) {
$pod_url = $secondary_pod_url;
$pod_url_used = 'main_module';
}
else {
$pod_url .= $format;
}
my $response = $self->http_client->get($pod_url);
if (not $response->{success} && ($pod_url_used = 'release')) {
warn "Could not find POD at $pod_url. Trying: $secondary_pod_url..";
$response = $self->http_client->get($secondary_pod_url);
if (not $response->{success}) {
warn "Could not find POD at $secondary_pod_url";
return $self->not_found_string;
}
}
my $content = $response->{content}; # if length $response->{content};
my @synopsis_lines = ();
my $seen_synopsis = my $seen_synopsis_end = 0;
my @content_lines = split '\n', $content;
foreach (@content_lines) {
# Are we starting the section after the Synopsis?
# if ($seen_synopsis && m/^#\s/) {
if ($seen_synopsis && m/^\S/) {
$seen_synopsis_end = 1;
}
# if (m/^#\s+SYNOPSIS/i) {
if (m/^SYNOPSIS/i) {
$seen_synopsis = 1;
}
if ($seen_synopsis && not $seen_synopsis_end) {
use Encode qw/ decode_utf8 encode_utf8/;
push @synopsis_lines, decode_utf8($_);
# push @synopsis_lines, $_;
}
}
return wantarray ? @synopsis_lines : join "\n", @synopsis_lines;
}
sub get_description_from_metacpan {
my ($self, $Module) = @_;
my $pod_url =
"http://api.metacpan.org/pod/${Module}?content-type=text/x-markdown";
my $response = $self->http_client->get($pod_url);
if (not $response->{success}) {
#warn "Failed to get URL: $pod_url";
return;
}
my $content = $response->{content}; # if length $response->{content};
my @description_lines = ();
my $seen_description = my $seen_description_end = 0;
my @content_lines = split '\n', $content;
foreach (@content_lines) {
# Are we starting the section after the Synopsis?
if ($seen_description && m/^#\s/) {
$seen_description_end = 1;
}
if (m/^#\s+DESCRIPTION/i) {
$seen_description = 1;
}
if ($seen_description && not $seen_description_end) {
push @description_lines, $_;
}
}
return wantarray ? @description_lines : join "\n", @description_lines;
}
=head2 get_synopsis_formatted
signature: (a Perl Module name, an element of qw/presentation/)
example: my $synop = $self->get_synopsis_formatted('Moose', 'presentation');
=cut
sub get_synopsis_formatted {
my ($self, $release, $format) = @_;
$format ||= 'presentation';
my $main_module_pod_url = my $main_module = $release->{distribution};
$main_module =~ s|-|::|g;
$main_module_pod_url =~ s|-|/|g;
$main_module_pod_url = "http://api.metacpan.org/pod/$release->{author}/$release->{name}/lib/${main_module_pod_url}.pm";
# Just have the presentation format for starters.
my $dispatch_table = {
presentation => sub {
my @synopsis_lines = $self->get_synopsis_from_metacpan($main_module, $main_module_pod_url);
@synopsis_lines = $self->trim_lines(@synopsis_lines);
if (not scalar @synopsis_lines) {
return $self->not_found_string;
}
my $abstract = '';
$abstract = "
\n" . $synopsis . "\n"; $synopsis = "