| 1 |
wakaba |
1.1 |
package Whatpm::CSS::Cascade; |
| 2 |
|
|
|
| 3 |
|
|
require Whatpm::CSS::Parser; ## NOTE: For property definitions. |
| 4 |
|
|
require Whatpm::CSS::SelectorsSerializer; |
| 5 |
|
|
use Scalar::Util qw/refaddr/; |
| 6 |
|
|
|
| 7 |
|
|
## Cascading and value computations |
| 8 |
|
|
|
| 9 |
|
|
sub new ($$) { |
| 10 |
|
|
my $self = bless {style_sheets => []}, shift; |
| 11 |
|
|
$self->{document} = shift; |
| 12 |
|
|
return $self; |
| 13 |
|
|
} # new |
| 14 |
|
|
|
| 15 |
|
|
## NOTE: This version does not support dynamic addition --- style |
| 16 |
|
|
## sheets must be added before any other operation. |
| 17 |
|
|
## NOTE: The $ss argument must be a value that can be interpreted as |
| 18 |
|
|
## an array reference of CSSStyleSheet objects. |
| 19 |
|
|
## NOTE: |type| and |media| attributes are not accounted by this |
| 20 |
|
|
## method (and any others in the class); CSSStyleSheet objects must |
| 21 |
|
|
## be filtered before they are passed to this method. |
| 22 |
|
|
sub add_style_sheets ($$) { |
| 23 |
|
|
my ($self, $ss) = @_; |
| 24 |
|
|
|
| 25 |
|
|
push @{$self->{style_sheets}}, @$ss; |
| 26 |
|
|
} # add_style_sheets |
| 27 |
|
|
|
| 28 |
|
|
## TODO: non-CSS presentation hints |
| 29 |
|
|
## TODO: style="" |
| 30 |
|
|
|
| 31 |
|
|
sub ___associate_rules ($) { |
| 32 |
|
|
my $self = shift; |
| 33 |
|
|
|
| 34 |
|
|
my $selectors_to_elements; |
| 35 |
|
|
|
| 36 |
|
|
for my $sheet (@{$self->{style_sheets}}) { |
| 37 |
|
|
## TODO: @media |
| 38 |
|
|
## TODO: @import |
| 39 |
|
|
## TODO: style sheet sources |
| 40 |
|
|
|
| 41 |
|
|
for my $rule (@{$sheet->css_rules}) { |
| 42 |
|
|
next if $rule->type != 1; # STYLE_RULE |
| 43 |
|
|
|
| 44 |
|
|
my $selectors_str = Whatpm::CSS::SelectorsSerializer->serialize_test |
| 45 |
|
|
($$rule->{_selectors}); |
| 46 |
|
|
unless ($selectors_to_elements->{$selectors_str}) { |
| 47 |
|
|
$selectors_to_elements->{$selectors_str} |
| 48 |
|
|
= $self->{document}->___query_selector_all ($$rule->{_selectors}); |
| 49 |
|
|
} |
| 50 |
|
|
|
| 51 |
|
|
push @{$self->{element_to_sd}->{refaddr $_} ||= []}, $rule->style |
| 52 |
|
|
for @{$selectors_to_elements->{$selectors_str}}; |
| 53 |
|
|
## TODO: specificity |
| 54 |
|
|
} |
| 55 |
|
|
} |
| 56 |
|
|
|
| 57 |
|
|
} # associate_rules |
| 58 |
|
|
|
| 59 |
|
|
sub get_cascaded_value ($$$) { |
| 60 |
|
|
my ($self, $element, $prop_name) = @_; |
| 61 |
|
|
return undef unless $Whatpm::CSS::Parser::Prop->{$prop_name}; |
| 62 |
|
|
|
| 63 |
|
|
my $key = $Whatpm::CSS::Parser::Prop->{$prop_name}->{key}; |
| 64 |
|
|
|
| 65 |
|
|
## TODO: cascading order |
| 66 |
|
|
for my $sd (reverse @{$self->{element_to_sd}->{refaddr $element} or []}) { |
| 67 |
|
|
my $vp = $$sd->{$key}; |
| 68 |
|
|
return $vp->[0] if defined $vp; |
| 69 |
|
|
} |
| 70 |
|
|
|
| 71 |
|
|
return undef; |
| 72 |
|
|
} # get_cascaded_value |
| 73 |
|
|
|
| 74 |
|
|
|
| 75 |
|
|
1; |
| 76 |
|
|
## $Date:$ |