Skip to content

Commit 4055902

Browse files
authored
Merge pull request #20 from sunnavy/master
Ignore deprecated "type" attribute of style tag and encode inlined styles
2 parents d9a1463 + a06af5b commit 4055902

File tree

3 files changed

+56
-11
lines changed

3 files changed

+56
-11
lines changed

lib/CSS/Inliner.pm

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use URI;
1212

1313
use CSS::Inliner::Parser;
1414
use CSS::Inliner::TreeBuilder;
15+
use HTML::Entities;
1516

1617
=pod
1718
@@ -42,7 +43,7 @@ sponsoring entity, MailerMailer LLC, has been sold to j2 Global.
4243
=cut
4344

4445
BEGIN {
45-
my $members = ['stylesheet','css','html','html_tree','query','strip_attrs','relaxed','leave_style','warns_as_errors','content_warnings','agent','fixlatin'];
46+
my $members = ['stylesheet','css','html','html_tree','query','strip_attrs','relaxed','leave_style','warns_as_errors','content_warnings','agent','fixlatin','encode_entities','ignore_style_type_attr'];
4647

4748
#generate all the getter/setter we need
4849
foreach my $member (@{$members}) {
@@ -77,6 +78,10 @@ leave_style - (optional) Leave style/link tags alone within <head> during inlini
7778
7879
relaxed - (optional) Relaxed HTML parsing which will attempt to interpret non-HTML4 documents.
7980
81+
encode_entities - (optional) Encode generated inline-styles (in case they contain HTML meta characters)
82+
83+
ignore_style_type_attr - (optional) Ignore the deprecated type attribute of "style" tag
84+
8085
NOTE: This argument is not compatible with passing an html_tree.
8186
8287
agent - (optional) Pass in a string containing a preferred user-agent, overrides the internal default provided by the module for handling remote documents
@@ -112,7 +117,9 @@ sub new {
112117
leave_style => (defined($$params{leave_style}) && $$params{leave_style}) ? 1 : 0,
113118
warns_as_errors => (defined($$params{warns_as_errors}) && $$params{warns_as_errors}) ? 1 : 0,
114119
agent => (defined($$params{agent}) && $$params{agent}) ? $$params{agent} : 'Mozilla/4.0',
115-
fixlatin => eval { require Encoding::FixLatin; return 1; } ? 1 : 0
120+
fixlatin => eval { require Encoding::FixLatin; return 1; } ? 1 : 0,
121+
encode_entities => (defined($$params{encode_entities}) && $$params{encode_entities}) ? 1 : 0,
122+
ignore_style_type_attr => (defined($$params{ignore_style_type_attr}) && $$params{ignore_style_type_attr}) ? 1 : 0,
116123
};
117124

118125
bless $self, $class;
@@ -492,15 +499,22 @@ sub inlinify {
492499

493500
# styles already inlined have greater precedence
494501
if (defined($element->attr('style'))) {
495-
my $cur_style = $self->_split({ style => $element->attr('style') });
502+
my $cur_style = $self->_split(
503+
{
504+
style => $self->_encode_entities
505+
? decode_entities($element->attr('style'))
506+
: $element->attr('style')
507+
}
508+
);
496509
push @new_style, @$cur_style;
497510
push @new_important_style, _grep_important_declarations($cur_style);
498511
}
499512

500513
# override styles with !important styles
501514
push @new_style, @new_important_style;
502515

503-
$element->attr('style', $self->_expand({ declarations => \@new_style }));
516+
my $new_style = $self->_expand({ declarations => \@new_style });
517+
$element->attr('style', $self->_encode_entities ? encode_entities($new_style) : $new_style);
504518
}
505519

506520
#at this point we have a document that contains the expanded inlined stylesheet
@@ -785,7 +799,7 @@ sub __expand_stylesheet {
785799
#absolutized the assetts within the stylesheet that are relative
786800
$content =~ s/(url\()["']?((?:(?!https?:\/\/)(?!\))[^"'])*)["']?(?=\))/$self->__fix_relative_url({ prefix => $1, url => $2, base => $baseref })/exsgi;
787801

788-
my $stylesheet = HTML::Element->new('style', type => 'text/css', rel=> 'stylesheet');
802+
my $stylesheet = HTML::Element->new('style', $self->_ignore_style_type_attr ? () : (type => 'text/css'));
789803
$stylesheet->push_content($content);
790804

791805
$i->replace_with($stylesheet);
@@ -801,7 +815,7 @@ sub __expand_stylesheet {
801815
# absolutize the assets within the stylesheet that are relative
802816
$content =~ s/(url\()["']?((?:(?!https?:\/\/)(?!\))[^"'])*)["']?(?=\))/$self->__fix_relative_url({ prefix => $1, url => $2, base => $baseref })/exsgi;
803817

804-
my $stylesheet = HTML::Element->new('style', type => 'text/css', rel=> 'stylesheet');
818+
my $stylesheet = HTML::Element->new('style', $self->_ignore_style_type_attr ? () : (type => 'text/css'));
805819
$stylesheet->push_content($content);
806820

807821
$i->replace_with($stylesheet);
@@ -870,7 +884,7 @@ sub _validate_html {
870884

871885
if ($body) {
872886
# located spurious <style> tags that won't be handled
873-
my @spurious_style = $body->look_down('_tag','style','type','text/css');
887+
my @spurious_style = $body->look_down('_tag','style', $self->_ignore_style_type_attr ? () : ('type','text/css'));
874888

875889
if (scalar @spurious_style) {
876890
$self->_report_warning({ info => 'Unexpected reference to stylesheet within document body skipped' });
@@ -892,7 +906,7 @@ sub _parse_stylesheet {
892906
my $stylesheet_root = $self->_relaxed() ? $self->_html_tree() : $self->_html_tree->look_down('_tag', 'head');
893907

894908
# get the <style> nodes
895-
my @style = $stylesheet_root->look_down('_tag','style','type','text/css');
909+
my @style = $stylesheet_root->look_down('_tag','style', $self->_ignore_style_type_attr ? () : ('type','text/css'));
896910

897911
foreach my $i (@style) {
898912
#process this node if the html media type is screen, all or undefined (which defaults to screen)
@@ -930,7 +944,7 @@ sub _collapse_inline_styles {
930944
if ($i->attr('style')) {
931945

932946
#flatten out the styles currently in place on this entity
933-
my $existing_styles = $i->attr('style');
947+
my $existing_styles = $self->_encode_entities ? decode_entities($i->attr('style')) : $i->attr('style');
934948
$existing_styles =~ tr/\n\t/ /;
935949

936950
# hold the property value pairs
@@ -948,7 +962,7 @@ sub _collapse_inline_styles {
948962
}
949963

950964
$collapsed_style =~ s/\s*$//;
951-
$i->attr('style', $collapsed_style);
965+
$i->attr('style', $self->_encode_entities ? encode_entities($collapsed_style) : $collapsed_style);
952966
}
953967

954968
#if we have specifically asked to remove the inlined attrs, remove them

t/embedded_style_block.t

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,23 @@ eval {
2323
};
2424

2525
## conditional test plan based on whether or not the endpoint can be reached - frequently can't by cpan testers
26-
plan $@ ? (skip_all => 'Connectivity for endpoint required for test cannot be established') : (tests => 1);
26+
plan $@ ? (skip_all => 'Connectivity for endpoint required for test cannot be established') : (tests => 2);
2727

2828
my $inlined = $inliner->inlinify();
2929

3030
ok($inlined eq $correct_result, 'result was correct');
31+
32+
$result_file = $html_path . 'embedded_style_result_encoded.html';
33+
34+
open( $fh, $result_file ) or die "can't open $result_file: $!!\n";
35+
$correct_result = do { local( $/ ) ; <$fh> } ;
36+
37+
$inliner = CSS::Inliner->new({encode_entities => 1});
38+
39+
eval {
40+
$inliner->fetch_file({ url => $test_url });
41+
};
42+
43+
$inlined = $inliner->inlinify();
44+
45+
ok($inlined eq $correct_result, 'result was correct');
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<html>
2+
<head>
3+
<meta content="text/html; charset=utf-8" http-equiv="Content-type" />
4+
</head>
5+
<body>
6+
<table id="layout" style="color: #0084ff; text-align: left;">
7+
<tr>
8+
<td id="header" style="color: #ff0000;">
9+
<div id="top" style="color: #259e00;">
10+
<p style="text-decoration: line-through; background: url(&#39;https://rawgit.com/images/background.png&#39;);">Email not displaying correctly? <a href="https://rawgit.com/view.html" style="font-size: 30px; color: #f5a100; font-weight: bold; text-decoration: underline;" title="View this email in your browser.">View it in your browser</a></p>
11+
</div>
12+
</td>
13+
</tr>
14+
</table>
15+
</body>
16+
</html>

0 commit comments

Comments
 (0)