Mojolicious-Plugin-Badge
view release on metacpan or search on metacpan
lib/Mojolicious/Plugin/Badge.pm view on Meta::CPAN
package Mojolicious::Plugin::Badge;
use Mojo::Base 'Mojolicious::Plugin';
use Carp ();
use Image::Magick;
use Mojo::ByteStream;
use Mojo::File qw(path);
use Mojo::URL;
use Mojo::UserAgent;
use Mojo::Util qw(b64_encode);
use Mojolicious::Types;
our $VERSION = '1.12';
use constant DEBUG => $ENV{BADGE_PLUGIN_DEBUG} || 0;
# Shields colors
my %SHIELDS_COLORS = (
brightgreen => '#4c1',
green => '#97ca00',
yellow => '#dfb317',
yellowgreen => '#a4a61d',
orange => '#fe7d37',
red => '#e05d44',
blue => '#007ec6',
grey => '#555',
lightgrey => '#9f9f9f',
# Alias
gray => '#555',
lightgray => '#9f9f9f',
critical => '#e05d44',
important => '#fe7d37',
success => '#4c1',
informational => '#007ec6',
inactive => '#9f9f9f',
);
my %NAMED_COLORS = (
aliceblue => '#f0f8ff',
antiquewhite => '#faebd7',
aqua => '#00ffff',
aquamarine => '#7fffd4',
azure => '#f0ffff',
beige => '#f5f5dc',
bisque => '#ffe4c4',
black => '#000000',
blanchedalmond => '#ffebcd',
blue => '#0000ff',
blueviolet => '#8a2be2',
brown => '#a52a2a',
burlywood => '#deb887',
cadetblue => '#5f9ea0',
chartreuse => '#7fff00',
chocolate => '#d2691e',
coral => '#ff7f50',
cornflowerblue => '#6495ed',
cornsilk => '#fff8dc',
crimson => '#dc143c',
cyan => '#00ffff',
darkblue => '#00008b',
darkcyan => '#008b8b',
darkgoldenrod => '#b886b',
darkgray => '#a9a9a9',
darkgreen => '#006400',
lib/Mojolicious/Plugin/Badge.pm view on Meta::CPAN
sandybrown => '#f4a460',
seagreen => '#2e8b57',
seashell => '#fff5ee',
sienna => '#a0522d',
silver => '#c0c0c0',
skyblue => '#87ceeb',
slateblue => '#6a5acd',
slategray => '#708090',
slategrey => '#708090',
snow => '#fffafa',
springgreen => '#00ff7f',
steelblue => '#4682b4',
tan => '#d2b48c',
teal => '#008080',
thistle => '#d8bfd8',
tomato => '#ff6347',
turquoise => '#40e0d0',
violet => '#ee82ee',
wheat => '#f5deb3',
white => '#ffffff',
whitesmoke => '#f5f5f5',
yellow => '#ffff00',
yellowgreen => '#9acd32',
);
sub register {
my ($self, $app, $config) = @_;
# Config
my $prefix = $config->{route} // $app->routes->any('/badge');
$prefix->to(return_to => $config->{return_to} // '/');
# Templates
my $resources = path(__FILE__)->sibling('Badge', 'resources');
push @{$app->renderer->paths}, $resources->child('templates')->to_string;
# Routes
if (!$config->{disable_api}) {
$prefix->get('/#content' => \&_badge_api)->to('content' => undef)->name('badge');
}
# Helpers
$app->helper('badge', sub { Mojo::ByteStream->new(_badge(@_)) });
}
sub _badge {
my ($c, %options) = @_;
my %badge_options = _build_options(%options);
DEBUG and $c->log->debug('[Badge] User Config', $c->app->dumper(\%options));
DEBUG and $c->log->debug('[Badge] Badge Config', $c->app->dumper(\%badge_options));
my $svg = $c->render_to_string('badge', format => 'svg', %badge_options);
if ($badge_options{badge_format} eq 'png') {
my $image = Image::Magick->new(magick => 'svg');
$image->BlobToImage($svg);
return $image->ImageToBlob(magick => 'png');
}
# Minify SVG
$svg =~ s/^(\s+)//mg;
$svg =~ s/\n//mg;
return $svg;
}
sub _build_options {
my (%options) = @_;
my $embed_logo = $options{embed_logo};
my $id_suffix = $options{id_suffix};
my $logo = $options{logo};
my $color = _decode_color($options{color} || 'informational');
my $link = $options{link};
my $title = $options{title};
my $style = $options{style} || 'flat';
my $badge_format = $options{badge_format} || 'svg';
if ($style !~ /^(flat|flat-square|plastic|for-the-badge)$/) {
Carp::croak 'Unknown badge style';
}
if ($badge_format !~ /^(png|svg)$/) {
Carp::croak 'Unknown badge format';
}
my $label = $options{label} || Carp::croak 'Missing label';
my $label_color = _decode_color($options{label_color} || 'gray');
my $label_link = $options{label_link};
my $label_text_color = _decode_color($options{label_text_color} || 'white');
my $label_title = $options{label_title};
my $message = $options{message};
my $message_link = $options{message_link};
my $message_text_color = _decode_color($options{message_text_color} || 'white');
my $message_title = $options{message_title};
if (($label_link || $message_link) && $link) {
Carp::croak '"link" may not bet set with "label_link" or "message_link"';
}
if ($style eq 'for-the-badge') {
$label = uc($label);
$message = uc($message) if ($message);
}
my $label_text_width = _get_text_width($label);
my $message_text_width = 0;
lib/Mojolicious/Plugin/Badge.pm view on Meta::CPAN
sub _embed_image {
my $image = shift;
my $ua = Mojo::UserAgent->new;
my $log = Mojo::Log->new->context('[Badge]');
my $content = undef;
my $content_type = undef;
if ($image =~ /^http/) {
my $url = (ref($image) ne 'Mojo::URL') ? Mojo::URL->new($image) : $image;
$log->info("Embedding image from URL: $url");
my $tx = $ua->get($url);
if (my $err = $tx->error) {
$log->error('Embed image error:', $err->{message});
return;
}
my $res = $tx->result;
$content_type = $res->headers->content_type;
if ($content_type !~ /^image/) {
$log->error(sprintf(q{URL doesn't contain an image (%s)}, $content_type));
return;
}
$content = $res->body;
}
if (-e $image) {
my $file = (ref($image) ne 'Mojo::File') ? Mojo::File->new($image) : $image;
my $types = Mojolicious::Types->new;
$content_type = $types->file_type($file);
if ($content_type !~ /^image/) {
$log->error(sprintf('File is not an image (%s)', $content_type));
return;
}
$content = $file->slurp;
}
return sprintf('data:%s;base64,%s', $content_type, b64_encode($content));
}
sub _get_text_width {
my ($text, %properties) = @_;
my $image = Image::Magick->new;
$properties{pointsize} ||= 110;
$properties{text} ||= $text;
$properties{gravity} ||= 'northwest';
$properties{font} ||= 'DejaVu-Sans';
$image->Set(size => '1x1');
$image->ReadImage('xc:none');
my ($x_ppem, $y_ppem, $ascender, $descender, $width, $height, $max_advance)
= $image->QueryMultilineFontMetrics(%properties);
return sprintf('%.0f', ($width / 10.0));
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Plugin::Badge - Badge Plugin for Mojolicious
=head1 SYNOPSIS
# Mojolicious
$self->plugin('Badge');
# Mojolicious::Lite
plugin 'Badge';
get '/my-cool-badge' => sub ($c) {
my $badge = $c->app->badge(
label => 'Hello',
message => 'Mojo!',
color => 'orange'
logo => 'https://docs.mojolicious.org/mojo/logo.png'
badge_format => 'png',
);
$c->render(data => $badge, format => 'png');
};
=head1 DESCRIPTION
L<Mojolicious::Plugin::Badge> is a L<Mojolicious> plugin that generate "Shields.io"
like badge from L</badge> helper or via API URL (e.g. C</badge/Hello-Mojo!-orange>).
=begin html
<p>
<img alt="Hello Mojo!" src="https://raw.github.com/giterlizzi/perl-Mojolicious-Plugin-Badge/main/examples/hello-mojo.png?raw=true">
</p>
=end html
( run in 2.556 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )