App-Music-ChordPro
view release on metacpan or search on metacpan
lib/ChordPro/lib/SVGPDF/CSS.pm view on Meta::CPAN
}
# 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);
my @spec = shellwords($s{$s});
foreach my $spec ( @spec ) {
$spec =~ s/;$//;
if ( $spec =~ /^([.\d]+)px/ ) {
$s{'font-size'} = $1;
}
elsif ( $spec eq "bold" ) {
$s{'font-weight'} = "bold";
}
elsif ( $spec eq "italic" ) {
$s{'font-style'} = "italic";
}
elsif ( $spec eq "bolditalic" ) {
$s{'font-weight'} = "bold";
$s{'font-style'} = "italic";
}
elsif ( $spec =~ /^(?:text,)?serif$/i ) {
$s{'font-family'} = "serif";
}
elsif ( $spec =~ /^(?:text,)?sans(?:-serif)?$/i ) {
$s{'font-family'} = "sans";
}
# These are for ABC SVG processing.
elsif ( $spec =~ /^abc2svg(?:\.ttf)?$/i ) {
$s{'font-family'} = "abc2svg";
}
elsif ( lc($spec) =~ /^musejazz\s*text$/i ) {
$s{'font-family'} = "musejazztext";
}
else {
$s{'font-family'} = $spec;
}
}
# Remove the shorthand if we found something.
delete($s{$s}) if keys(%s) > 1;
}
# Split outline shorthand.
elsif ( $s eq "outline" ) {
use Text::ParseWords qw(shellwords);
my @spec = shellwords($s{$s});
foreach my $spec ( @spec ) {
$spec =~ s/;$//;
if ( $spec =~ /^([.\d]+)px/ ) {
$s{'outline-width'} = $1;
}
elsif ( $spec =~ /^(dotted|dashed|solid|double|groove|ridge|inset|outset)$/i ) {
$s{'outline-style'} = $1;
}
else {
$s{'outline-color'} = $spec;
}
}
# Remove the shorthand if we found something.
delete($s{$s}) if keys(%s) > 1;
}
foreach my $k ( keys %s ) {
foreach ( @styles ) {
$css->{$_}->{$k} = $s{$k};
}
}
}
}
my @keys = keys( %$css );
for my $k ( @keys ) {
if ( $k =~ /^\@font-face/ ) {
# Unhide semicolons.
s/\x{ff1b}/;/g for values( %{$css->{$k}} );
( run in 0.568 second using v1.01-cache-2.11-cpan-98e64b0badf )