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 )