BBCode-Parser
view release on metacpan or search on metacpan
lib/BBCode/Util.pm view on Meta::CPAN
# Emulation of <font size="num">...</font> from HTML 3.2
# See <URL:http://www.w3.org/TR/CSS21/fonts.html#font-size-props>
# Tweaked slightly to be more logical
my @compat = qw(xx-small x-small small medium large x-large xx-large 300%);
BEGIN { _export qw(parseFontSize parse) }
sub parseFontSize($;$$$);
sub parseFontSize($;$$$) {
local $_ = shift;
return undef unless defined $_;
my($base,$lo,$hi) = @_;
$base = 12 if not defined $base;
$lo = 8 if not defined $lo;
$hi = 72 if not defined $hi;
s/\s+/ /g;
s/^\s|\s$//g;
# CSS 2.1 15.7 <absolute-size>
if(/^( (?:xx?-)? (?:large|small) | medium )$/ix) {
return lc $1;
}
# CSS 2.1 15.7 <relative-size>
# Note: Since [FONT] is nestable and not readily computable before HTML
# rendering, this can allow a malicious user to escape the
# admin-defined font size limits
if(/^ ( larger | smaller ) $/ix) {
return lc $1;
}
# CSS 2.1 4.3.2 <length>
if(/^ ( [\s\d._+-]+ ) ( [a-z]+ ) $/ix) {
my($n,$unit) = ($1,lc $2);
$n = parseNum $n;
if(defined $n and $n > 0) {
my $conv;
if(exists $conv{$unit}) {
$conv = $conv{$unit};
} elsif($unit =~ /^em$/i) {
$conv = $base;
} elsif($unit =~ /^ex$/i) {
$conv = $base * 0.5;
} else {
return undef;
}
my $n2 = $n * $conv;
if(defined $lo and $n2 < $lo) {
$n = $lo / $conv;
} elsif(defined $hi and $n2 > $hi) {
$n = $hi / $conv;
}
$n = sprintf "%.3f", $n;
$n =~ s/0+$//;
$n =~ s/\.$//;
return "$n$unit";
} else {
return undef;
}
}
# CSS 2.1 4.3.3 <percentage>
# Note: The same concerns apply as for <relative-size>
if(/^ ( [\s\d._+-]+ ) % $/x) {
my $n = parseNum $1;
if(defined $n and $n > 0) {
$n *= 0.01;
my $n2 = $n * $base;
if(defined $lo and $n2 < $lo) {
$n = $lo / $base;
} elsif(defined $hi and $n2 > $hi) {
$n = $hi / $base;
}
$n *= 100;
$n = sprintf "%.3f", $n;
$n =~ s/0+$//;
$n =~ s/\.$//;
return "$n%";
} else {
return undef;
}
}
# HTML 3.2 <font size="number">
# See <URL:http://www.w3.org/TR/REC-html32#font>
if(/^ (\d+) $/x) {
my $n = 0+$1;
if($n >= 0 and $n < @compat) {
return $compat[$n];
} else {
return parseFontSize("$n pt",$base,$lo,$hi);
}
}
# HTML 3.2 <font size="+number">
if(/^ \+ (\d+) $/x) {
# "+1" is roughly equivalent to CSS 2.1 "larger"
my $n = sprintf "%f%%", 100 * (1.25 ** $1);
return parseFontSize($n,$base,$lo,$hi);
}
# HTML 3.2 <font size="-number">
if(/^ - (\d+) $/x) {
# "-1" is roughly equivalent to CSS 2.1 "smaller"
my $n = sprintf "%f%%", 100 * (0.85 ** $1);
return parseFontSize($n,$base,$lo,$hi);
}
return undef;
}
# Official CSS 2.1 colors are passed through as-is
my %cssColor = map { $_ => 1 } qw(
maroon red orange yellow olive
purple fuchsia white lime green
navy blue aqua teal
black silver gray
);
# Other named colors must map to an official named color or an #RRGGBB color
my %extraColor = (
darkred => 'maroon',
( run in 0.776 second using v1.01-cache-2.11-cpan-39bf76dae61 )