inline-style-umanni 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ class InlineStyle
2
+ # A simple abstraction of the data we get back from the parsers. CSSPool
3
+ # actually already does this for us but CSSParser does not so we need
4
+ # to create the abstraction ourselves.
5
+ class Rule
6
+ DYNAMIC_PSEUDO_CLASSES = %w(link visited active hover focus target enabled disabled checked)
7
+ DYNAMIC_PSEUDO_CLASSES_MATCHER = /:(#{DYNAMIC_PSEUDO_CLASSES.join('|')})$/
8
+
9
+ attr_reader :selector, :declarations, :specificity, :dynamic_pseudo_class
10
+
11
+ def initialize selector, declarations, specificity
12
+ @specificity = specificity
13
+ @selector, @dynamic_pseudo_class = selector.split DYNAMIC_PSEUDO_CLASSES_MATCHER
14
+ @selector.sub! /$^/, '*'
15
+ @declarations = declarations.scan /\s*([^:]+):\s*([^;]+);/
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ class InlineStyle
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,90 @@
1
+ require "spec_helper"
2
+
3
+ describe InlineStyle do
4
+ shared_examples_for 'inlines styles' do
5
+ before do
6
+ processed = InlineStyle.process File.read("#{FIXTURES}/boletin.html"), :stylesheets_path => FIXTURES
7
+ @processed = Nokogiri.HTML(processed)
8
+ end
9
+
10
+ it "should extract from linked stylesheet" do
11
+ @processed.css('#izq').first['style'].should match_style /margin: 30.0px;/
12
+ end
13
+
14
+ it "should extract styles from linked stylesheet with no media specified" do
15
+ @processed.css('#izq').first['style'].should match_style /color: red;/
16
+ end
17
+
18
+ it "should extract styles from linked stylesheet with media 'all'" do
19
+ @processed.css('#izq').first['style'].should match_style /border: none;/
20
+ end
21
+
22
+ it "should ignore styles from linked stylesheet with media other than screen" do
23
+ @processed.css('#izq').first['style'].should_not match_style /display: none;/
24
+ end
25
+
26
+ it "should not process pseudo classes" do
27
+ @processed.css('a').first['style'].should_not match_style /^:hover \{background-color: #8ae0ea; color: #126b5d;\}$/
28
+ end
29
+
30
+ it 'should process location-based pseudo classes' do
31
+ @processed.at_css('#izq')['style'].should match_style /padding: 1.0px;/
32
+ end
33
+
34
+ it 'should apply to #A #B' do
35
+ @processed.css('#logos #der').first['style'].should match_style /float: right;/
36
+ end
37
+
38
+ it 'should not override rules defined inline' do
39
+ @processed.css('#aviso').first['style'].should match_style /color: green;/
40
+ end
41
+
42
+ it 'should overwrite rule previously defined' do
43
+ @processed.css('#izq').first['style'].should_not match_style /padding: 0.0;/
44
+ end
45
+
46
+ describe 'Box model' do
47
+ before do
48
+ @processed = InlineStyle.process(Nokogiri.HTML(File.read("#{FIXTURES}/box-model.html")))
49
+ end
50
+
51
+ it "should inline style for selector ul" do
52
+ @processed.css('ul').first['style'].should match_style /^background: yellow; margin: 12.0px 12.0px 12.0px 12.0px; padding: 3.0px 3.0px 3.0px 3.0px;$/
53
+ end
54
+
55
+ it "should inline style for selector li" do
56
+ @processed.css('li').each do |li|
57
+ li['style'].should match_style /^color: white; background: blue; margin: 12.0px 12.0px 12.0px 12.0px; padding: 12.0px 0.0px 12.0px 12.0px; list-style: none/
58
+ end
59
+ end
60
+
61
+ it "should inline style for selector li.withborder" do
62
+ @processed.css('li.withborder').first['style'].
63
+ should match_style /^color: white; background: blue; margin: 12.0px 12.0px 12.0px 12.0px; padding: 12.0px 0.0px 12.0px 12.0px; list-style: none; border-style: dashed; border-width: medium; border-color: lime;$/
64
+ end
65
+ end
66
+ end
67
+
68
+ describe CssParser do
69
+ it { InlineStyle::CSSParser.should == InlineStyle::CssParserWrapper }
70
+ it_should_behave_like 'inlines styles'
71
+ end
72
+
73
+ describe CSSPool do
74
+ before do
75
+ class InlineStyle
76
+ remove_const :CSSParser
77
+ CSSParser = InlineStyle::CSSPoolWrapper
78
+ end
79
+ end
80
+
81
+ after do
82
+ class InlineStyle
83
+ remove_const :CSSParser
84
+ CSSParser = InlineStyle::CssParserWrapper
85
+ end
86
+ end
87
+ it { InlineStyle::CSSParser.should == InlineStyle::CSSPoolWrapper }
88
+ it_should_behave_like 'inlines styles'
89
+ end
90
+ end
@@ -0,0 +1,146 @@
1
+ require "spec_helper"
2
+
3
+ describe 'CSS parsing' do
4
+ shared_examples_for 'parses css' do
5
+ describe 'parsing tag selector' do
6
+ before do
7
+ @wrapper = subject.new 'p {background-color: black; padding: 0.0 0.0 0.0 0.0}'
8
+ end
9
+
10
+ it { @wrapper.should have(1).rules }
11
+
12
+ describe 'rule' do
13
+ before { @rule = @wrapper.rules.first }
14
+ it { @rule.specificity.should == '0001' }
15
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
16
+ it { @rule.selector.should == 'p' }
17
+ it { @rule.dynamic_pseudo_class.should be_nil }
18
+ end
19
+ end
20
+
21
+ describe 'parsing body tag selector' do
22
+ before do
23
+ @wrapper = subject.new 'body {background-color: black; padding: 0.0 0.0 0.0 0.0}'
24
+ end
25
+
26
+ it { @wrapper.should have(1).rules }
27
+
28
+ describe 'rule' do
29
+ before { @rule = @wrapper.rules.first }
30
+ it { @rule.specificity.should == '0001' }
31
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
32
+ it { @rule.selector.should == 'body' }
33
+ it { @rule.dynamic_pseudo_class.should be_nil }
34
+ end
35
+ end
36
+
37
+ describe 'parsing tag and class selector' do
38
+ before do
39
+ @wrapper = subject.new 'div.article {background-color: black; padding: 0.0 0.0 0.0 0.0}'
40
+ end
41
+
42
+ it { @wrapper.should have(1).rules }
43
+
44
+ describe 'rule' do
45
+ before { @rule = @wrapper.rules.first }
46
+ it { @rule.specificity.should == '0011' }
47
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
48
+ it { @rule.selector.should == 'div.article' }
49
+ it { @rule.dynamic_pseudo_class.should be_nil }
50
+ end
51
+ end
52
+
53
+ describe 'parsing tag, class and id selector' do
54
+ before do
55
+ @wrapper = subject.new 'div#headline.article {background-color: black; padding: 0.0 0.0 0.0 0.0}'
56
+ end
57
+
58
+ it { @wrapper.should have(1).rules }
59
+
60
+ describe 'rule' do
61
+ before { @rule = @wrapper.rules.first }
62
+ it { @rule.specificity.should == '0111' }
63
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
64
+ it { @rule.selector.should == 'div#headline.article' }
65
+ it { @rule.dynamic_pseudo_class.should be_nil }
66
+ end
67
+ end
68
+
69
+ describe 'parsing tag selector' do
70
+ before do
71
+ @wrapper = subject.new 'p, div {background-color: black; padding: 0.0 0.0 0.0 0.0}'
72
+ end
73
+
74
+ it { @wrapper.should have(2).rules }
75
+
76
+ describe 'first rule' do
77
+ before { @rule = @wrapper.rules.first }
78
+ it { @rule.specificity.should == '0001' }
79
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
80
+ it { @rule.selector.should == 'p' }
81
+ it { @rule.dynamic_pseudo_class.should be_nil }
82
+ end
83
+
84
+ describe 'last rule' do
85
+ before { @rule = @wrapper.rules.last }
86
+ it { @rule.specificity.should == '0001' }
87
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
88
+ it { @rule.selector.should == 'div' }
89
+ it { @rule.dynamic_pseudo_class.should be_nil }
90
+ end
91
+ end
92
+
93
+ describe 'dynamic pseudo selectors' do
94
+ InlineStyle::Rule::DYNAMIC_PSEUDO_CLASSES.each do |pseudo_class|
95
+ describe "parsing tag with :#{pseudo_class}" do
96
+ before { @dynamic_pseudo_class = pseudo_class }
97
+ it_should_behave_like 'parses dynamic pseudo selector'
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ shared_examples_for 'parses dynamic pseudo selector' do
104
+ describe 'with tag' do
105
+ before do
106
+ @wrapper = subject.new "p:#{@dynamic_pseudo_class} {background-color: black; padding: 0.0 0.0 0.0 0.0}"
107
+ end
108
+
109
+ it { @wrapper.should have(1).rules }
110
+
111
+ describe 'rule' do
112
+ before { @rule = @wrapper.rules.first }
113
+ # it { @rule.specificity.should == '011' }
114
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
115
+ it { @rule.selector.should == 'p' }
116
+ it { @rule.dynamic_pseudo_class.should == @dynamic_pseudo_class }
117
+ end
118
+ end
119
+
120
+ describe 'without tag' do
121
+ before do
122
+ @wrapper = subject.new ":#{@dynamic_pseudo_class} {background-color: black; padding: 0.0 0.0 0.0 0.0}"
123
+ end
124
+
125
+ it { @wrapper.should have(1).rules }
126
+
127
+ describe 'rule' do
128
+ before { @rule = @wrapper.rules.first }
129
+ # it { @rule.specificity.should == '011' }
130
+ it { @rule.declarations.should == [['background-color', 'black'], ['padding', '0.0 0.0 0.0 0.0']] }
131
+ it { @rule.selector.should == '*' }
132
+ it { @rule.dynamic_pseudo_class.should == @dynamic_pseudo_class }
133
+ end
134
+ end
135
+ end
136
+
137
+ describe InlineStyle::CssParserWrapper do
138
+ subject { InlineStyle::CssParserWrapper }
139
+ it_should_behave_like 'parses css'
140
+ end
141
+
142
+ describe InlineStyle::CssParserWrapper do
143
+ subject { InlineStyle::CSSPoolWrapper }
144
+ it_should_behave_like 'parses css'
145
+ end
146
+ end
@@ -0,0 +1,3 @@
1
+ #izq {
2
+ border: none;
3
+ }
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+
3
+ <html xmlns="http://www.w3.org/1999/xhtml">
4
+ <head>
5
+ <meta content="text/html; charset=utf-8" http-equiv="Content-type" />
6
+ <title> Boletín CENART - November
7
+ </title>
8
+
9
+ <link href="/style.css?1248460539" rel="stylesheet" media="screen" type="text/css" />
10
+
11
+ <link href="/print.css?1248460539" rel="stylesheet" media="print" type="text/css" />
12
+ <link href="/all.css?1248460539" rel="stylesheet" media="all" type="text/css" />
13
+ <link href="/none.css?1248460539" rel="stylesheet" type="text/css" />
14
+
15
+
16
+
17
+ </head>
18
+
19
+ <body>
20
+ <style media="screen" type="text/css">
21
+ * {
22
+ margin: 0;
23
+ padding: 0;
24
+ }
25
+
26
+ body {
27
+ font: 13px "Lucida Grande", Lucida, Verdana, sans-serif;
28
+ width: 680px;
29
+ color: #373737;
30
+ margin-left: auto;
31
+ margin-right: auto;
32
+ }
33
+
34
+ p {
35
+ margin: 10px 0;
36
+ }
37
+
38
+ .clearer {
39
+ clear: both;
40
+ }
41
+
42
+ #banner {
43
+ margin: 15px;
44
+ text-align: right;
45
+ color: #639b22;
46
+ }
47
+
48
+ #banner span {
49
+ font-size: 20px;
50
+ }
51
+
52
+ #aviso {
53
+ padding: 25px 0;
54
+ text-align: center;
55
+ color: blue;
56
+ }
57
+
58
+ dl.categoria dt {
59
+ font-size: 20px;
60
+ padding: 10px;
61
+ background-color: #416517;
62
+ border-bottom: 1px dashed #a6a6a6;
63
+ color: #a0bf57;
64
+ }
65
+
66
+ dl.evento, div#direccion, div#contacto {
67
+ padding: 30px 25px 20px 35px;
68
+ }
69
+
70
+ dl.evento {
71
+ border-bottom: 1px dashed #a6a6a6;
72
+ }
73
+
74
+ dl.evento.non {
75
+ background-color: #d9e3cf;
76
+ }
77
+
78
+ dl.evento.par {
79
+ background-color: #cfdfe3;
80
+ }
81
+
82
+ dl.evento dt {
83
+ padding: 0;
84
+ font-size: 20px;
85
+ background: none;
86
+ font-weight: bold;
87
+ border: none;
88
+ }
89
+
90
+ a, b {
91
+ color: #185d6b;
92
+ }
93
+
94
+ a:hover {
95
+ background-color: #8ae0ea;
96
+ color: #126b5d;
97
+ }
98
+
99
+ dl.evento dd {
100
+ text-align: justify;
101
+ margin: 10px 0;
102
+ }
103
+
104
+ dd.poster {
105
+ float: right;
106
+ }
107
+
108
+ dd.poster img {
109
+ border: 1px solid #909090;
110
+ margin: 0 0 25px 25px;
111
+ }
112
+
113
+ div#footer b {
114
+ color: #5f792d;
115
+ }
116
+
117
+ div#contacto a {
118
+ font-weight: bold;
119
+ font-size: 1.2em;
120
+ }
121
+
122
+ #logos {
123
+ width: 100%;
124
+ margin-top: 40px;
125
+ background-image: url('/images/boletines/Noviembre/logos_fondo.jpg');
126
+ }
127
+
128
+ #logos img:first-child {
129
+ padding: 1px;
130
+ }
131
+
132
+ #izq {
133
+ float: left;
134
+ }
135
+
136
+ #logos #der {
137
+ float: right;
138
+ }
139
+
140
+
141
+ </style>
142
+
143
+
144
+
145
+
146
+ <div id="header">
147
+ <div id="aviso" style='color: green;'>Si usted no puede visualizar correctamente este boletín haga <a href="http://localhost:3000/boletines/noviembre-2009">click aquí</a></div>
148
+ <div id="banner"><span id="cenart">CENART</span> Noviembre 2009</div>
149
+ </div>
150
+
151
+
152
+
153
+
154
+
155
+ <dl class="categoria" id="A">
156
+ <dt>A</dt>
157
+ <dd>
158
+
159
+
160
+ <dl class="evento non">
161
+ <dt><a href="">1</a></dt>
162
+
163
+ <dd class="descripcion"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
164
+ </dd>
165
+ <dd class="fechas"><b>Fechas: </b>Fecha</dd>
166
+ <dd class="locacion"><b>Lugar: </b>Lugar</dd>
167
+ <dd class="precio"><b>Público: </b>Público</dd>
168
+ <dd class="precio"><b>Precio: </b>Precio</dd>
169
+ </dl>
170
+
171
+
172
+ </dd>
173
+ </dl>
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+ <dl class="categoria" id="B">
184
+ <dt>B</dt>
185
+ <dd>
186
+
187
+
188
+ <dl class="evento par">
189
+ <dt><a href="">1</a></dt>
190
+
191
+ <dd class="descripcion"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
192
+ </dd>
193
+ <dd class="fechas"><b>Fechas: </b>Fecha</dd>
194
+ <dd class="locacion"><b>Lugar: </b>Lugar</dd>
195
+ <dd class="precio"><b>Público: </b>Público</dd>
196
+ <dd class="precio"><b>Precio: </b>Precio</dd>
197
+ </dl>
198
+
199
+
200
+ </dd>
201
+ </dl>
202
+
203
+
204
+
205
+
206
+
207
+ <dl class="categoria" id="C">
208
+ <dt>C</dt>
209
+ <dd>
210
+
211
+
212
+ <dl class="evento non">
213
+ <dt><a href="">1</a></dt>
214
+
215
+ <dd class="descripcion"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
216
+ </dd>
217
+ <dd class="fechas"><b>Fechas: </b>Fecha</dd>
218
+ <dd class="locacion"><b>Lugar: </b>Lugar</dd>
219
+ <dd class="precio"><b>Público: </b>Público</dd>
220
+ <dd class="precio"><b>Precio: </b>Precio</dd>
221
+ </dl>
222
+
223
+
224
+ </dd>
225
+ </dl>
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+ <div id="footer">
238
+ <div id="direccion">
239
+ <b>lorem</b><br/ >
240
+ ipsum<br />
241
+ dolor<br />
242
+ sit<br />
243
+ </div>
244
+
245
+ <div id="contacto">
246
+ contacto <br />
247
+ <a href="mailto:mail@host.org">mail@host.org</a>
248
+ </div>
249
+ <div id="logos">
250
+ <img src="A" id="izq" alt="A" />
251
+ <img src="B" id="der" alt="B" />
252
+ <div class="clearer">
253
+ </div>
254
+ </div>
255
+
256
+
257
+
258
+ </div></body>
259
+
260
+
261
+ </html>