App-Music-ChordPro
view release on metacpan or search on metacpan
lib/ChordPro/lib/SVGPDF/CSS.pm view on Meta::CPAN
#! perl
use v5.26;
use Object::Pad;
use utf8;
use Carp;
class SVGPDF::CSS;
field $css :accessor;
field $errstr :accessor;
field $base :mutator;
field $ctx :accessor;
field @stack;
field $ffam :accessor;
BUILD {
$css = {};
$base =
{ 'font-family' => 'serif',
'font-size' => '10',
'color' => 'black',
'background-color' => 'none',
'fill' => 'currentColor',
'stroke' => 'none',
'line-width' => 1,
};
$ctx = {};
$ffam = [];
$self->push( @_ ) if @_;
}
# Parse a string with one or more styles. Augments.
method read_string ( $string ) {
state $ffi = "face000"; # for unique font-face ids
$css->{'*'} //= $base;
# Flatten whitespace and remove /* comment */ style comments.
$string =~ s/\s+/ /g;
$string =~ s!/\*.*?\*\/!!g;
# Hide semicolon in url(data:application/octet-stream;base64,...)
$string =~ s/(url\(['"]data:.*?\/.*?);(.*?),/$1\x{ff1b}$2,/g;
# Split into styles.
foreach ( grep { /\S/ } split /(?<=\})/, $string ) {
unless ( /^\s*([^{]+?)\s*\{(.*)\}\s*$/ ) {
$errstr = "Invalid or unexpected style data '$_'";
return;
}
# Split in such a way as to support grouped styles.
my $style = $1;
my $properties = $2;
$style =~ s/\s{2,}/ /g;
my @styles =
grep { s/\s+/ /g; 1; }
grep { /\S/ }
split( /\s*,\s*/, $style );
foreach ( @styles ) {
# Give @font-face rules an unique id.
if ( $_ eq '@font-face' ) {
$_ = '@font-'.$ffi;
$ffi++;
}
$css->{$_} //= {};
}
# Split into properties.
foreach ( grep { /\S/ } split /\;/, $properties ) {
unless ( /^\s*(\*?[\w._-]+)\s*:\s*(.*?)\s*$/ ) {
$errstr = "Invalid or unexpected property '$_' in style '$style'";
return;
}
my $s = lc($1);
my %s = ( $s => $2 );
# Split font shorthand.
if ( $s eq "font" ) {
use Text::ParseWords qw(shellwords);
( run in 1.310 second using v1.01-cache-2.11-cpan-f56aa216473 )