CSS-Scopifier
view release on metacpan or search on metacpan
lib/CSS/Scopifier/Group.pm view on Meta::CPAN
package CSS::Scopifier::Group;
use strict;
use warnings;
# ABSTRACT: Like CSS::Scopifier, but can handle rule groups
use Moo;
use Types::Standard qw(:all);
use CSS::Scopifier;
use Path::Class qw(file);
use Text::Balanced qw(extract_bracketed);
has 'group_name', is => 'ro', isa => Maybe[Str], default => sub {undef};
has 'local', is => 'ro', isa => InstanceOf['CSS::Scopifier'], default => sub { CSS::Scopifier->new };
has '_members', is => 'ro', isa => ArrayRef, default => sub {[]};
sub scopify {
my $self = shift;
$_->scopify(@_) for ($self->local,@{$self->_members});
return 1;
}
sub write_string {
my $self = shift;
join("\n",
$self->local->write_string,
map { join('',$_->group_name," \{\n",$_->write_string,"\n\}\n") } @{$self->_members}
)
}
sub read {
my ($class, $file) = @_;
$class->read_string( scalar file($file)->resolve->slurp )
}
sub read_string {
my $self = ref $_[0] ? shift : (shift)->new;
my $string = shift;
# Flatten whitespace and remove /* comment */ style comments (copied from CSS::Tiny)
$string =~ tr/\n\t/ /;
$string =~ s!/\*.*?\*\/!!g;
my $local = '';
while($string) {
my ($extracted,$remainder,$skipped) = extract_bracketed( $string, '{}', '[^\{]*' );
my ($pre,$inner) = ($skipped,$extracted);
if($pre) {
$pre =~ s/^\s+//;
$pre =~ s/\s+$//;
}
if($inner) {
$inner =~ s/^\{//;
$inner =~ s/\}$//;
}
# we consider this to be a 'group' if it starts with '@' and contains
# additional curly brace(s) within (i.e. @media print { h1 { ... } })
if($pre && $inner && $pre =~ /^\@/ && $inner =~ /\{/) {
push @{$self->_members}, (ref $self)
->new({ group_name => $pre })
->read_string($inner)
}
else {
$self->local->read_string( join('', $skipped||'', $extracted||'') )
}
$string = $remainder;
last unless ($extracted);
}
( run in 1.339 second using v1.01-cache-2.11-cpan-39bf76dae61 )