Mo-utils-CSS
view release on metacpan or search on metacpan
package Mo::utils::CSS;
use base qw(Exporter);
use strict;
use warnings;
use Error::Pure qw(err);
use Graphics::ColorNames::CSS;
use List::Util 1.33 qw(any none);
use Mo::utils::Array qw(check_array);
use Mo::utils::Number::Utils qw(sub_check_percent);
use Readonly;
Readonly::Array our @EXPORT_OK => qw(check_array_css_color check_css_border
check_css_class check_css_color check_css_unit);
Readonly::Array our @ABSOLUTE_LENGTHS => qw(cm mm in px pt pc);
Readonly::Array our @BORDER_GLOBAL => qw(inherit initial revert revert-layer unset);
Readonly::Array our @BORDER_STYLES => qw(none hidden dotted dashed solid double groove ridge inset outset);
Readonly::Array our @BORDER_WIDTHS => qw(thin medium thick);
Readonly::Array our @RELATIVE_LENGTHS => qw(em ex ch rem vw vh vmin vmax %);
Readonly::Array our @COLOR_FUNC => qw(rgb rgba hsl hsla);
our $VERSION = 0.13;
sub check_array_css_color {
my ($self, $key) = @_;
if (! exists $self->{$key}) {
return;
}
check_array($self, $key);
foreach my $css_color (@{$self->{$key}}) {
_check_color($css_color, $key);
}
return;
}
sub check_css_border {
my ($self, $key) = @_;
_check_key($self, $key) && return;
# Global values.
if (any { $self->{$key} eq $_ } @BORDER_GLOBAL) {
return;
}
my @parts = split m/\s+/ms, $self->{$key}, 3;
if (@parts == 1) {
_check_border_style($self->{$key}, $key);
} elsif (@parts == 2) {
# Border style on first place.
if (any { $parts[0] eq $_ } @BORDER_STYLES) {
_check_color($parts[1], $key, $self->{$key});
# Border style on second place.
} elsif (any { $parts[1] eq $_ } @BORDER_STYLES) {
if (none { $parts[0] eq $_ } @BORDER_WIDTHS) {
_check_unit($parts[0], $key, $self->{$key});
}
} else {
err "Parameter '$key' hasn't border style.",
'Value', $self->{$key},
;
}
} else {
if (none { $parts[0] eq $_ } @BORDER_WIDTHS) {
_check_unit($parts[0], $key, $self->{$key});
}
_check_border_style($parts[1], $key, $self->{$key});
_check_color($parts[2], $key, $self->{$key});
}
return;
}
sub check_css_class {
my ($self, $key) = @_;
_check_key($self, $key) && return;
if ($self->{$key} !~ m/^[a-zA-Z0-9\-_]+$/ms) {
err "Parameter '$key' has bad CSS class name.",
'Value', $self->{$key},
;
} elsif ($self->{$key} =~ m/^\d/ms) {
err "Parameter '$key' has bad CSS class name (number on begin).",
'Value', $self->{$key},
;
}
return;
}
sub check_css_color {
my ($self, $key) = @_;
_check_key($self, $key) && return;
_check_color($self->{$key}, $key);
return;
}
sub check_css_unit {
my ($self, $key) = @_;
_check_key($self, $key) && return;
_check_unit($self->{$key}, $key);
return;
}
sub _check_alpha {
my ($alpha, $key, $func, $error_value) = @_;
if ($alpha !~ m/^[\d\.]+$/ms || $alpha > 1) {
err "Parameter '$key' has bad $func alpha.",
'Value', $error_value,
;
}
return;
}
sub _check_border_style {
my ($value, $key, $error_value) = @_;
if (! defined $error_value) {
$error_value = $value;
}
if (none { $value eq $_ } @BORDER_STYLES) {
err "Parameter '$key' has bad border style.",
'Value', $error_value,
;
}
return;
}
sub _check_color {
my ($value, $key, $error_value) = @_;
if (! defined $error_value) {
$error_value = $value;
}
my $funcs = join '|', @COLOR_FUNC;
if ($value =~ m/^#(.*)$/ms) {
my $rgb = $1;
if (length $rgb == 3 || length $rgb == 6 || length $rgb == 8) {
if ($rgb !~ m/^[0-9A-Fa-f]+$/ms) {
err "Parameter '$key' has bad rgb color (bad hex number).",
'Value', $error_value,
;
}
} else {
err "Parameter '$key' has bad rgb color (bad length).",
'Value', $error_value,
;
}
} elsif ($value =~ m/^($funcs)\((.*)\)$/ms) {
my $func = $1;
my $args_string = $2;
my @args = split m/\s*,\s*/ms, $args_string;
if ($func eq 'rgb') {
if (@args != 3) {
err "Parameter '$key' has bad rgb color (bad number of arguments).",
'Value', $error_value,
;
}
_check_colors([@args[0 .. 2]], $key, $func, $error_value);
} elsif ($func eq 'rgba') {
if (@args != 4) {
err "Parameter '$key' has bad rgba color (bad number of arguments).",
'Value', $error_value,
;
}
_check_colors([@args[0 .. 2]], $key, $func, $error_value);
_check_alpha($args[3], $key, $func, $error_value);
} elsif ($func eq 'hsl') {
if (@args != 3) {
err "Parameter '$key' has bad hsl color (bad number of arguments).",
'Value', $error_value,
;
}
_check_degree($args[0], $key, $func, $error_value);
_check_percent([@args[1 .. 2]], $key, $func.' percent', $error_value);
# hsla
} else {
if (@args != 4) {
err "Parameter '$key' has bad hsla color (bad number of arguments).",
'Value', $error_value,
;
}
_check_degree($args[0], $key, $func, $error_value);
_check_percent([@args[1 .. 2]], $key, $func.' percent', $error_value);
_check_alpha($args[3], $key, $func, $error_value);
}
} else {
if (none { $value eq $_ } keys %{Graphics::ColorNames::CSS->NamesRgbTable}) {
err "Parameter '$key' has bad color name.",
'Value', $error_value,
;
}
}
return;
}
sub _check_colors {
my ($value_ar, $key, $func, $error_value) = @_;
foreach my $i (@{$value_ar}) {
if ($i !~ m/^\d+$/ms || $i > 255) {
err "Parameter '$key' has bad $func color (bad number).",
'Value', $error_value,
;
}
}
return;
}
sub _check_degree {
( run in 1.403 second using v1.01-cache-2.11-cpan-71847e10f99 )