OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library declaration_test; | 5 library declaration_test; |
6 | 6 |
| 7 import 'package:csslib/src/messages.dart'; |
| 8 import 'package:csslib/visitor.dart'; |
7 import 'package:test/test.dart'; | 9 import 'package:test/test.dart'; |
8 | 10 |
9 import 'testing.dart'; | 11 import 'testing.dart'; |
10 | 12 |
| 13 void expectCss(String css, String expected) { |
| 14 var errors = <Message>[]; |
| 15 var styleSheet = parseCss(css, errors: errors, opts: simpleOptions); |
| 16 expect(styleSheet, isNotNull); |
| 17 expect(errors, isEmpty); |
| 18 expect(prettyPrint(styleSheet), expected); |
| 19 } |
| 20 |
11 void testSimpleTerms() { | 21 void testSimpleTerms() { |
12 var errors = []; | 22 var errors = <Message>[]; |
13 final String input = r''' | 23 final String input = r''' |
14 @ import url("test.css"); | 24 @ import url("test.css"); |
15 .foo { | 25 .foo { |
16 background-color: #191919; | 26 background-color: #191919; |
| 27 content: "u+0041"; |
17 width: 10PX; | 28 width: 10PX; |
18 height: 22mM !important; | 29 height: 22mM !important; |
19 border-width: 20cm; | 30 border-width: 20cm; |
20 margin-width: 33%; | 31 margin-width: 33%; |
21 border-height: 30EM; | 32 border-height: 30EM; |
22 width: .6in; | 33 width: .6in; |
23 length: 1.2in; | 34 length: 1.2in; |
24 -web-stuff: -10Px; | 35 -web-stuff: -10Px; |
25 }'''; | 36 }'''; |
26 final String generated = r''' | 37 final String generated = r''' |
27 @import "test.css"; | 38 @import "test.css"; |
28 .foo { | 39 .foo { |
29 background-color: #191919; | 40 background-color: #191919; |
| 41 content: "u+0041"; |
30 width: 10px; | 42 width: 10px; |
31 height: 22mm !important; | 43 height: 22mm !important; |
32 border-width: 20cm; | 44 border-width: 20cm; |
33 margin-width: 33%; | 45 margin-width: 33%; |
34 border-height: 30em; | 46 border-height: 30em; |
35 width: .6in; | 47 width: .6in; |
36 length: 1.2in; | 48 length: 1.2in; |
37 -web-stuff: -10px; | 49 -web-stuff: -10px; |
38 }'''; | 50 }'''; |
39 | 51 |
(...skipping 10 matching lines...) Expand all Loading... |
50 final String generated2 = r''' | 62 final String generated2 = r''' |
51 * { | 63 * { |
52 border-color: #008000; | 64 border-color: #008000; |
53 }'''; | 65 }'''; |
54 | 66 |
55 stylesheet = parseCss(input2, errors: errors..clear()); | 67 stylesheet = parseCss(input2, errors: errors..clear()); |
56 | 68 |
57 expect(stylesheet != null, true); | 69 expect(stylesheet != null, true); |
58 expect(errors.isEmpty, true, reason: errors.toString()); | 70 expect(errors.isEmpty, true, reason: errors.toString()); |
59 expect(prettyPrint(stylesheet), generated2); | 71 expect(prettyPrint(stylesheet), generated2); |
| 72 |
| 73 // Regression test to ensure invalid percentages don't throw an exception and |
| 74 // instead print a useful error message when not in checked mode. |
| 75 var css = ''' |
| 76 .foo { |
| 77 width: Infinity%; |
| 78 }'''; |
| 79 stylesheet = parseCss(css, errors: errors..clear(), opts: simpleOptions); |
| 80 expect(errors, isNotEmpty); |
| 81 expect(errors.first.message, 'expected }, but found %'); |
| 82 expect(errors.first.span.text, '%'); |
60 } | 83 } |
61 | 84 |
62 /** | 85 /** |
63 * Declarations with comments, references with single-quotes, double-quotes, | 86 * Declarations with comments, references with single-quotes, double-quotes, |
64 * no quotes. Hex values with # and letters, and functions (rgba, url, etc.) | 87 * no quotes. Hex values with # and letters, and functions (rgba, url, etc.) |
65 */ | 88 */ |
66 void testDeclarations() { | 89 void testDeclarations() { |
67 var errors = []; | 90 var errors = <Message>[]; |
68 final String input = r''' | 91 final String input = r''' |
69 .more { | 92 .more { |
70 color: white; | 93 color: white; |
71 color: black; | 94 color: black; |
72 color: cyan; | 95 color: cyan; |
73 color: red; | 96 color: red; |
74 color: #aabbcc; /* test -- 3 */ | 97 color: #aabbcc; /* test -- 3 */ |
75 color: blue; | 98 color: blue; |
76 background-image: url(http://test.jpeg); | 99 background-image: url(http://test.jpeg); |
77 background-image: url("http://double_quote.html"); | 100 background-image: url("http://double_quote.html"); |
(...skipping 17 matching lines...) Expand all Loading... |
95 }'''; | 118 }'''; |
96 | 119 |
97 var stylesheet = parseCss(input, errors: errors); | 120 var stylesheet = parseCss(input, errors: errors); |
98 | 121 |
99 expect(stylesheet != null, true); | 122 expect(stylesheet != null, true); |
100 expect(errors.isEmpty, true, reason: errors.toString()); | 123 expect(errors.isEmpty, true, reason: errors.toString()); |
101 expect(prettyPrint(stylesheet), generated); | 124 expect(prettyPrint(stylesheet), generated); |
102 } | 125 } |
103 | 126 |
104 void testIdentifiers() { | 127 void testIdentifiers() { |
105 var errors = []; | 128 var errors = <Message>[]; |
106 final String input = r''' | 129 final String input = r''' |
107 #da { | 130 #da { |
108 height: 100px; | 131 height: 100px; |
109 } | 132 } |
110 #foo { | 133 #foo { |
111 width: 10px; | 134 width: 10px; |
112 color: #ff00cc; | 135 color: #ff00cc; |
113 } | 136 } |
114 '''; | 137 '''; |
115 final String generated = r''' | 138 final String generated = r''' |
116 #da { | 139 #da { |
117 height: 100px; | 140 height: 100px; |
118 } | 141 } |
119 #foo { | 142 #foo { |
120 width: 10px; | 143 width: 10px; |
121 color: #f0c; | 144 color: #f0c; |
122 }'''; | 145 }'''; |
123 | 146 |
124 var stylesheet = parseCss(input, errors: errors); | 147 var stylesheet = parseCss(input, errors: errors); |
125 | 148 |
126 expect(errors.isEmpty, true, reason: errors.toString()); | 149 expect(errors.isEmpty, true, reason: errors.toString()); |
127 expect(stylesheet != null, true); | 150 expect(stylesheet != null, true); |
128 expect(prettyPrint(stylesheet), generated); | 151 expect(prettyPrint(stylesheet), generated); |
129 } | 152 } |
130 | 153 |
131 void testComposites() { | 154 void testComposites() { |
132 var errors = []; | 155 var errors = <Message>[]; |
133 final String input = r''' | 156 final String input = r''' |
134 .xyzzy { | 157 .xyzzy { |
135 border: 10px 80px 90px 100px; | 158 border: 10px 80px 90px 100px; |
136 width: 99%; | 159 width: 99%; |
137 } | 160 } |
138 @-webkit-keyframes pulsate { | 161 @-webkit-keyframes pulsate { |
139 0% { | 162 0% { |
140 -webkit-transform: translate3d(0, 0, 0) scale(1.0); | 163 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
141 } | 164 } |
142 }'''; | 165 }'''; |
143 final String generated = r''' | 166 final String generated = r''' |
144 .xyzzy { | 167 .xyzzy { |
145 border: 10px 80px 90px 100px; | 168 border: 10px 80px 90px 100px; |
146 width: 99%; | 169 width: 99%; |
147 } | 170 } |
148 @-webkit-keyframes pulsate { | 171 @-webkit-keyframes pulsate { |
149 0% { | 172 0% { |
150 -webkit-transform: translate3d(0, 0, 0) scale(1.0); | 173 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
151 } | 174 } |
152 }'''; | 175 }'''; |
153 | 176 |
154 var stylesheet = parseCss(input, errors: errors); | 177 var stylesheet = parseCss(input, errors: errors); |
155 expect(stylesheet != null, true); | 178 expect(stylesheet != null, true); |
156 expect(errors.isEmpty, true, reason: errors.toString()); | 179 expect(errors.isEmpty, true, reason: errors.toString()); |
157 expect(prettyPrint(stylesheet), generated); | 180 expect(prettyPrint(stylesheet), generated); |
158 } | 181 } |
159 | 182 |
160 void testUnits() { | 183 void testUnits() { |
161 var errors = []; | 184 var errors = <Message>[]; |
162 final String input = r''' | 185 final String input = r''' |
163 #id-1 { | 186 #id-1 { |
164 transition: color 0.4s; | 187 transition: color 0.4s; |
165 animation-duration: 500ms; | 188 animation-duration: 500ms; |
166 top: 1em; | 189 top: 1em; |
167 left: 200ex; | 190 left: 200ex; |
168 right: 300px; | 191 right: 300px; |
169 bottom: 400cm; | 192 bottom: 400cm; |
170 border-width: 2.5mm; | 193 border-width: 2.5mm; |
171 margin-top: .5in; | 194 margin-top: -.5in; |
172 margin-left: 5pc; | 195 margin-left: +5pc; |
173 margin-right: 5ex; | 196 margin-right: 5ex; |
174 margin-bottom: 5ch; | 197 margin-bottom: 5ch; |
175 font-size: 10pt; | 198 font-size: 10pt; |
176 padding-top: 22rem; | 199 padding-top: 22rem; |
177 padding-left: 33vw; | 200 padding-left: 33vw; |
178 padding-right: 34vh; | 201 padding-right: 34vh; |
179 padding-bottom: 3vmin; | 202 padding-bottom: 3vmin; |
180 transform: rotate(20deg); | 203 transform: rotate(20deg); |
181 voice-pitch: 10hz; | 204 voice-pitch: 10hz; |
182 } | 205 } |
(...skipping 16 matching lines...) Expand all Loading... |
199 | 222 |
200 final String generated = r''' | 223 final String generated = r''' |
201 #id-1 { | 224 #id-1 { |
202 transition: color 0.4s; | 225 transition: color 0.4s; |
203 animation-duration: 500ms; | 226 animation-duration: 500ms; |
204 top: 1em; | 227 top: 1em; |
205 left: 200ex; | 228 left: 200ex; |
206 right: 300px; | 229 right: 300px; |
207 bottom: 400cm; | 230 bottom: 400cm; |
208 border-width: 2.5mm; | 231 border-width: 2.5mm; |
209 margin-top: .5in; | 232 margin-top: -.5in; |
210 margin-left: 5pc; | 233 margin-left: +5pc; |
211 margin-right: 5ex; | 234 margin-right: 5ex; |
212 margin-bottom: 5ch; | 235 margin-bottom: 5ch; |
213 font-size: 10pt; | 236 font-size: 10pt; |
214 padding-top: 22rem; | 237 padding-top: 22rem; |
215 padding-left: 33vw; | 238 padding-left: 33vw; |
216 padding-right: 34vh; | 239 padding-right: 34vh; |
217 padding-bottom: 3vmin; | 240 padding-bottom: 3vmin; |
218 transform: rotate(20deg); | 241 transform: rotate(20deg); |
219 voice-pitch: 10hz; | 242 voice-pitch: 10hz; |
220 } | 243 } |
(...skipping 14 matching lines...) Expand all Loading... |
235 }'''; | 258 }'''; |
236 | 259 |
237 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); | 260 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
238 | 261 |
239 expect(stylesheet != null, true); | 262 expect(stylesheet != null, true); |
240 expect(errors.isEmpty, true, reason: errors.toString()); | 263 expect(errors.isEmpty, true, reason: errors.toString()); |
241 expect(prettyPrint(stylesheet), generated); | 264 expect(prettyPrint(stylesheet), generated); |
242 } | 265 } |
243 | 266 |
244 void testUnicode() { | 267 void testUnicode() { |
245 var errors = []; | 268 var errors = <Message>[]; |
246 final String input = r''' | 269 final String input = r''' |
247 .toggle:after { | 270 .toggle:after { |
248 content: '✔'; | 271 content: '✔'; |
249 line-height: 43px; | 272 line-height: 43px; |
250 font-size: 20px; | 273 font-size: 20px; |
251 color: #d9d9d9; | 274 color: #d9d9d9; |
252 text-shadow: 0 -1px 0 #bfbfbf; | 275 text-shadow: 0 -1px 0 #bfbfbf; |
253 } | 276 } |
254 '''; | 277 '''; |
255 | 278 |
256 final String generated = r''' | 279 final String generated = r''' |
257 .toggle:after { | 280 .toggle:after { |
258 content: '✔'; | 281 content: '✔'; |
259 line-height: 43px; | 282 line-height: 43px; |
260 font-size: 20px; | 283 font-size: 20px; |
261 color: #d9d9d9; | 284 color: #d9d9d9; |
262 text-shadow: 0 -1px 0 #bfbfbf; | 285 text-shadow: 0 -1px 0 #bfbfbf; |
263 }'''; | 286 }'''; |
264 | 287 |
265 var stylesheet = parseCss(input, errors: errors); | 288 var stylesheet = parseCss(input, errors: errors); |
266 | 289 |
267 expect(stylesheet != null, true); | 290 expect(stylesheet != null, true); |
268 expect(errors.isEmpty, true, reason: errors.toString()); | 291 expect(errors.isEmpty, true, reason: errors.toString()); |
269 expect(prettyPrint(stylesheet), generated); | 292 expect(prettyPrint(stylesheet), generated); |
270 } | 293 } |
271 | 294 |
272 void testNewerCss() { | 295 void testNewerCss() { |
273 var errors = []; | 296 var errors = <Message>[]; |
274 final String input = r''' | 297 final String input = r''' |
275 @media screen,print { | 298 @media screen,print { |
276 .foobar_screen { | 299 .foobar_screen { |
277 width: 10px; | 300 width: 10px; |
278 } | 301 } |
279 } | 302 } |
280 @page { | 303 @page { |
281 height: 22px; | 304 height: 22px; |
282 size: 3in 3in; | 305 size: 3in 3in; |
283 } | 306 } |
284 @page : left { | 307 @page : left { |
285 width: 10px; | 308 width: 10px; |
286 } | 309 } |
287 @page bar : left { @top-left { margin: 8px; } } | 310 @page bar : left { @top-left { margin: 8px; } } |
| 311 @page { @top-left { margin: 8px; } width: 10px; } |
288 @charset "ISO-8859-1"; | 312 @charset "ISO-8859-1"; |
289 @charset 'ASCII';'''; | 313 @charset 'ASCII';'''; |
290 | 314 |
291 final String generated = r''' | 315 final String generated = r''' |
292 @media screen, print { | 316 @media screen, print { |
293 .foobar_screen { | 317 .foobar_screen { |
294 width: 10px; | 318 width: 10px; |
295 } | 319 } |
296 } | 320 } |
297 @page { | 321 @page { |
298 height: 22px; | 322 height: 22px; |
299 size: 3in 3in; | 323 size: 3in 3in; |
300 } | 324 } |
301 @page:left { | 325 @page:left { |
302 width: 10px; | 326 width: 10px; |
303 } | 327 } |
304 @page bar:left { | 328 @page bar:left { |
305 @top-left { | 329 @top-left { |
306 margin: 8px; | 330 margin: 8px; |
307 } | 331 } |
308 } | 332 } |
| 333 @page { |
| 334 @top-left { |
| 335 margin: 8px; |
| 336 } |
| 337 width: 10px; |
| 338 } |
309 @charset "ISO-8859-1"; | 339 @charset "ISO-8859-1"; |
310 @charset "ASCII";'''; | 340 @charset "ASCII";'''; |
311 | 341 |
312 var stylesheet = parseCss(input, errors: errors); | 342 var stylesheet = parseCss(input, errors: errors); |
313 | 343 |
314 expect(stylesheet != null, true); | 344 expect(stylesheet != null, true); |
315 expect(errors.isEmpty, true, reason: errors.toString()); | 345 expect(errors.isEmpty, true, reason: errors.toString()); |
316 expect(prettyPrint(stylesheet), generated); | 346 expect(prettyPrint(stylesheet), generated); |
317 } | 347 } |
318 | 348 |
319 void testMediaQueries() { | 349 void testMediaQueries() { |
320 var errors = []; | 350 var errors = <Message>[]; |
321 String input = ''' | 351 String input = ''' |
322 @media screen and (-webkit-min-device-pixel-ratio:0) { | 352 @media screen and (-webkit-min-device-pixel-ratio:0) { |
323 .todo-item .toggle { | 353 .todo-item .toggle { |
324 background: none; | 354 background: none; |
325 } | 355 } |
326 #todo-item .toggle { | 356 #todo-item .toggle { |
327 height: 40px; | 357 height: 40px; |
328 } | 358 } |
329 }'''; | 359 }'''; |
330 String generated = ''' | 360 String generated = ''' |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 } | 392 } |
363 }'''; | 393 }'''; |
364 generated = | 394 generated = |
365 '''@media handheld AND (min-width:20em), screen AND (min-width:20em) { | 395 '''@media handheld AND (min-width:20em), screen AND (min-width:20em) { |
366 #id { | 396 #id { |
367 color: #f00; | 397 color: #f00; |
368 } | 398 } |
369 .myclass { | 399 .myclass { |
370 height: 20px; | 400 height: 20px; |
371 } | 401 } |
372 } @media print AND (min-resolution:300dpi) { | 402 } |
| 403 @media print AND (min-resolution:300dpi) { |
373 #anotherId { | 404 #anotherId { |
374 color: #fff; | 405 color: #fff; |
375 } | 406 } |
376 } @media print AND (min-resolution:280dpcm) { | 407 } |
| 408 @media print AND (min-resolution:280dpcm) { |
377 #finalId { | 409 #finalId { |
378 color: #aaa; | 410 color: #aaa; |
379 } | 411 } |
380 .class2 { | 412 .class2 { |
381 border: 20px; | 413 border: 20px; |
382 } | 414 } |
383 }'''; | 415 }'''; |
384 | 416 |
385 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); | 417 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
386 | 418 |
387 expect(stylesheet != null, true); | 419 expect(stylesheet != null, true); |
388 expect(errors.isEmpty, true, reason: errors.toString()); | 420 expect(errors.isEmpty, true, reason: errors.toString()); |
389 expect(prettyPrint(stylesheet), generated); | 421 expect(prettyPrint(stylesheet), generated); |
390 | 422 |
391 input = ''' | 423 input = ''' |
392 @media only screen and (min-device-width: 4000px) and | 424 @media only screen and (min-device-width: 4000px) and |
393 (min-device-height: 2000px), screen (another: 100px) { | 425 (min-device-height: 2000px), screen AND (another: 100px) { |
394 html { | 426 html { |
395 font-size: 10em; | 427 font-size: 10em; |
396 } | 428 } |
397 }'''; | 429 }'''; |
398 generated = '@media ONLY screen AND (min-device-width:4000px) ' | 430 generated = '@media ONLY screen AND (min-device-width:4000px) ' |
399 'AND (min-device-height:2000px), screen (another:100px) {\n' | 431 'AND (min-device-height:2000px), screen AND (another:100px) {\n' |
400 'html {\n font-size: 10em;\n}\n}'; | 432 'html {\n font-size: 10em;\n}\n}'; |
401 | 433 |
402 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); | 434 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
403 | 435 |
404 expect(stylesheet != null, true); | 436 expect(stylesheet != null, true); |
405 expect(errors.isEmpty, true, reason: errors.toString()); | 437 expect(errors.isEmpty, true, reason: errors.toString()); |
406 expect(prettyPrint(stylesheet), generated); | 438 expect(prettyPrint(stylesheet), generated); |
407 | 439 |
408 input = ''' | 440 input = ''' |
409 @media screen,print (min-device-width: 4000px) and | 441 @media screen,print AND (min-device-width: 4000px) and |
410 (min-device-height: 2000px), screen (another: 100px) { | 442 (min-device-height: 2000px), screen AND (another: 100px) { |
411 html { | 443 html { |
412 font-size: 10em; | 444 font-size: 10em; |
413 } | 445 } |
414 }'''; | 446 }'''; |
415 generated = '@media screen, print (min-device-width:4000px) AND ' | 447 generated = '@media screen, print AND (min-device-width:4000px) AND ' |
416 '(min-device-height:2000px), screen (another:100px) {\n' | 448 '(min-device-height:2000px), screen AND (another:100px) {\n' |
417 'html {\n font-size: 10em;\n}\n}'; | 449 'html {\n font-size: 10em;\n}\n}'; |
418 | 450 |
419 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); | 451 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
420 | 452 |
421 expect(stylesheet != null, true); | 453 expect(stylesheet != null, true); |
422 expect(errors.isEmpty, true, reason: errors.toString()); | 454 expect(errors.isEmpty, true, reason: errors.toString()); |
423 expect(prettyPrint(stylesheet), generated); | 455 expect(prettyPrint(stylesheet), generated); |
424 | 456 |
425 input = ''' | 457 input = ''' |
426 @import "test.css" ONLY screen, NOT print (min-device-width: 4000px);'''; | 458 @import "test.css" ONLY screen, NOT print AND (min-device-width: 4000px);'''; |
427 generated = | 459 generated = '@import "test.css" ONLY screen, ' |
428 '@import "test.css" ONLY screen, NOT print (min-device-width:4000px);'; | 460 'NOT print AND (min-device-width:4000px);'; |
429 | 461 |
430 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); | 462 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
431 | 463 |
432 expect(stylesheet != null, true); | 464 expect(stylesheet != null, true); |
433 expect(errors.isEmpty, true, reason: errors.toString()); | 465 expect(errors.isEmpty, true, reason: errors.toString()); |
434 expect(prettyPrint(stylesheet), generated); | 466 expect(prettyPrint(stylesheet), generated); |
| 467 |
| 468 var css = '@media (min-device-width:400px) {\n}'; |
| 469 expectCss(css, css); |
| 470 |
| 471 css = '@media all AND (tranform-3d), (-webkit-transform-3d) {\n}'; |
| 472 expectCss(css, css); |
| 473 |
| 474 // Test that AND operator is required between media type and expressions. |
| 475 css = '@media screen (min-device-width:400px'; |
| 476 stylesheet = parseCss(css, errors: errors..clear(), opts: simpleOptions); |
| 477 expect(errors, isNotEmpty); |
| 478 expect( |
| 479 errors.first.message, contains('expected { after media before ruleset')); |
| 480 expect(errors.first.span.text, '('); |
| 481 } |
| 482 |
| 483 void testMozDocument() { |
| 484 var errors = <Message>[]; |
| 485 // Test empty url-prefix, commonly used for browser detection. |
| 486 var css = ''' |
| 487 @-moz-document url-prefix() { |
| 488 div { |
| 489 color: #000; |
| 490 } |
| 491 }'''; |
| 492 var expected = '''@-moz-document url-prefix() { |
| 493 div { |
| 494 color: #000; |
| 495 } |
| 496 }'''; |
| 497 var styleSheet = parseCss(css, errors: errors); |
| 498 expect(styleSheet, isNotNull); |
| 499 expect(errors, isEmpty); |
| 500 expect(prettyPrint(styleSheet), expected); |
| 501 |
| 502 // Test url-prefix with unquoted parameter |
| 503 css = ''' |
| 504 @-moz-document url-prefix(http://www.w3.org/Style/) { |
| 505 div { |
| 506 color: #000; |
| 507 } |
| 508 }'''; |
| 509 expected = '''@-moz-document url-prefix("http://www.w3.org/Style/") { |
| 510 div { |
| 511 color: #000; |
| 512 } |
| 513 }'''; |
| 514 styleSheet = parseCss(css, errors: errors); |
| 515 expect(styleSheet, isNotNull); |
| 516 expect(errors, isEmpty); |
| 517 expect(prettyPrint(styleSheet), expected); |
| 518 |
| 519 // Test domain with unquoted parameter |
| 520 css = ''' |
| 521 @-moz-document domain(google.com) { |
| 522 div { |
| 523 color: #000; |
| 524 } |
| 525 }'''; |
| 526 expected = '''@-moz-document domain("google.com") { |
| 527 div { |
| 528 color: #000; |
| 529 } |
| 530 }'''; |
| 531 styleSheet = parseCss(css, errors: errors); |
| 532 expect(styleSheet, isNotNull); |
| 533 expect(errors, isEmpty); |
| 534 expect(prettyPrint(styleSheet), expected); |
| 535 |
| 536 // Test all document functions combined. |
| 537 css = '@-moz-document ' + |
| 538 'url(http://www.w3.org/), ' + |
| 539 "url-prefix('http://www.w3.org/Style/'), " + |
| 540 'domain("google.com"), ' + |
| 541 'regexp("https:.*") { div { color: #000; } }'; |
| 542 expected = '@-moz-document ' + |
| 543 'url("http://www.w3.org/"), ' + |
| 544 'url-prefix("http://www.w3.org/Style/"), ' + |
| 545 'domain("google.com"), ' + |
| 546 'regexp("https:.*") {\ndiv {\n color: #000;\n}\n}'; |
| 547 styleSheet = parseCss(css, errors: errors); |
| 548 expect(styleSheet, isNotNull); |
| 549 expect(errors, isEmpty); |
| 550 expect(prettyPrint(styleSheet), expected); |
| 551 } |
| 552 |
| 553 void testSupports() { |
| 554 // Test single declaration condition. |
| 555 var css = ''' |
| 556 @supports (-webkit-appearance: none) { |
| 557 div { |
| 558 -webkit-appearance: none; |
| 559 } |
| 560 }'''; |
| 561 var expected = '''@supports (-webkit-appearance: none) { |
| 562 div { |
| 563 -webkit-appearance: none; |
| 564 } |
| 565 }'''; |
| 566 expectCss(css, expected); |
| 567 |
| 568 // Test negation. |
| 569 css = ''' |
| 570 @supports not ( display: flex ) { |
| 571 body { width: 100%; } |
| 572 }'''; |
| 573 expected = '''@supports not (display: flex) { |
| 574 body { |
| 575 width: 100%; |
| 576 } |
| 577 }'''; |
| 578 expectCss(css, expected); |
| 579 |
| 580 // Test clause with multiple conditions. |
| 581 css = ''' |
| 582 @supports (box-shadow: 0 0 2px black inset) or |
| 583 (-moz-box-shadow: 0 0 2px black inset) or |
| 584 (-webkit-box-shadow: 0 0 2px black inset) or |
| 585 (-o-box-shadow: 0 0 2px black inset) { |
| 586 .box { |
| 587 box-shadow: 0 0 2px black inset; |
| 588 } |
| 589 }'''; |
| 590 expected = '@supports (box-shadow: 0 0 2px #000 inset) or ' + |
| 591 '(-moz-box-shadow: 0 0 2px #000 inset) or ' + |
| 592 '(-webkit-box-shadow: 0 0 2px #000 inset) or ' + |
| 593 '(-o-box-shadow: 0 0 2px #000 inset) {\n' + |
| 594 '.box {\n' + |
| 595 ' box-shadow: 0 0 2px #000 inset;\n' + |
| 596 '}\n' + |
| 597 '}'; |
| 598 expectCss(css, expected); |
| 599 |
| 600 // Test conjunction and disjunction together. |
| 601 css = ''' |
| 602 @supports ((transition-property: color) or (animation-name: foo)) and |
| 603 (transform: rotate(10deg)) { |
| 604 div { |
| 605 transition-property: color; |
| 606 transform: rotate(10deg); |
| 607 } |
| 608 }'''; |
| 609 |
| 610 expected = '@supports ' + |
| 611 '((transition-property: color) or (animation-name: foo)) and ' + |
| 612 '(transform: rotate(10deg)) {\n' + |
| 613 'div {\n' + |
| 614 ' transition-property: color;\n' + |
| 615 ' transform: rotate(10deg);\n' + |
| 616 '}\n' + |
| 617 '}'; |
| 618 expectCss(css, expected); |
| 619 |
| 620 // Test that operators can't be mixed without parentheses. |
| 621 css = '@supports (a: 1) and (b: 2) or (c: 3) {}'; |
| 622 var errors = <Message>[]; |
| 623 var styleSheet = parseCss(css, errors: errors, opts: simpleOptions); |
| 624 expect(styleSheet, isNotNull); |
| 625 expect(errors, isNotEmpty); |
| 626 expect(errors.first.message, |
| 627 "Operators can't be mixed without a layer of parentheses"); |
| 628 expect(errors.first.span.text, 'or'); |
| 629 } |
| 630 |
| 631 void testViewport() { |
| 632 // No declarations. |
| 633 var css = '@viewport {\n}'; |
| 634 expectCss(css, css); |
| 635 |
| 636 // All declarations. |
| 637 css = ''' |
| 638 @viewport { |
| 639 min-width: auto; |
| 640 max-width: 800px; |
| 641 width: 400px; |
| 642 min-height: 50%; |
| 643 max-height: 200px; |
| 644 height: 100px 200px; |
| 645 zoom: auto; |
| 646 min-zoom: 0.75; |
| 647 max-zoom: 40%; |
| 648 user-zoom: fixed; |
| 649 orientation: landscape; |
| 650 }'''; |
| 651 expectCss(css, css); |
| 652 |
| 653 // Vendor specific. |
| 654 css = ''' |
| 655 @-ms-viewport { |
| 656 width: device-width; |
| 657 }'''; |
| 658 expectCss(css, css); |
435 } | 659 } |
436 | 660 |
437 void testFontFace() { | 661 void testFontFace() { |
438 var errors = []; | 662 var errors = <Message>[]; |
439 | 663 |
440 final String input = ''' | 664 final String input = ''' |
441 @font-face { | 665 @font-face { |
442 font-family: BBCBengali; | 666 font-family: BBCBengali; |
443 src: url(fonts/BBCBengali.ttf) format("opentype"); | 667 src: url(fonts/BBCBengali.ttf) format("opentype"); |
444 unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???; | 668 unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???; |
445 }'''; | 669 }'''; |
446 final String generated = '''@font-face { | 670 final String generated = '''@font-face { |
447 font-family: BBCBengali; | 671 font-family: BBCBengali; |
448 src: url("fonts/BBCBengali.ttf") format("opentype"); | 672 src: url("fonts/BBCBengali.ttf") format("opentype"); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF; | 744 unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF; |
521 }'''; | 745 }'''; |
522 stylesheet = parseCss(input4, errors: errors..clear(), opts: simpleOptions); | 746 stylesheet = parseCss(input4, errors: errors..clear(), opts: simpleOptions); |
523 | 747 |
524 expect(stylesheet != null, true); | 748 expect(stylesheet != null, true); |
525 expect(errors.isEmpty, true, reason: errors.toString()); | 749 expect(errors.isEmpty, true, reason: errors.toString()); |
526 expect(prettyPrint(stylesheet), generated4); | 750 expect(prettyPrint(stylesheet), generated4); |
527 } | 751 } |
528 | 752 |
529 void testCssFile() { | 753 void testCssFile() { |
530 var errors = []; | 754 var errors = <Message>[]; |
531 final String input = r''' | 755 final String input = r''' |
532 @import 'simple.css' | 756 @import 'simple.css' |
533 @import "test.css" print | 757 @import "test.css" print |
534 @import url(test.css) screen, print | 758 @import url(test.css) screen, print |
535 @import url(http://google.com/maps/maps.css); | 759 @import url(http://google.com/maps/maps.css); |
536 | 760 |
537 div[href^='test'] { | 761 div[href^='test'] { |
538 height: 10px; | 762 height: 10px; |
539 } | 763 } |
540 | 764 |
541 @-webkit-keyframes pulsate { | 765 @-webkit-keyframes pulsate { |
542 from { | 766 from { |
543 -webkit-transform: translate3d(0, 0, 0) scale(1.0); | 767 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
544 } | 768 } |
545 10% { | 769 10% { |
546 -webkit-transform: translate3d(0, 0, 0) scale(1.0); | 770 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
547 } | 771 } |
548 30% { | 772 30% { |
549 -webkit-transform: translate3d(0, 2, 0) scale(1.0); | 773 -webkit-transform: translate3d(0, 2, 0) scale(1.0); |
550 } | 774 } |
551 } | 775 } |
552 | 776 |
553 .foobar { | 777 .foobar { |
554 grid-columns: 10px ("content" 1fr 10px)[4]; | 778 grid-columns: 10px ("content" 1fr 10px)[4]; |
555 } | 779 } |
556 | 780 |
557 .test-background { | 781 .test-background { |
558 background: url(http://www.foo.com/bar.png); | 782 background: url(http://www.foo.com/bar.png); |
559 } | 783 } |
| 784 |
| 785 .test-background-with-multiple-properties { |
| 786 background: #000 url(http://www.foo.com/bar.png); |
| 787 } |
560 '''; | 788 '''; |
561 | 789 |
562 final String generated = '@import "simple.css"; ' | 790 final String generated = '@import "simple.css"; ' |
563 '@import "test.css" print; ' | 791 '@import "test.css" print; ' |
564 '@import "test.css" screen, print; ' | 792 '@import "test.css" screen, print; ' |
565 '@import "http://google.com/maps/maps.css";\n' | 793 '@import "http://google.com/maps/maps.css";\n' |
566 'div[href^="test"] {\n' | 794 'div[href^="test"] {\n' |
567 ' height: 10px;\n' | 795 ' height: 10px;\n' |
568 '}\n' | 796 '}\n' |
569 '@-webkit-keyframes pulsate {\n' | 797 '@-webkit-keyframes pulsate {\n' |
570 ' from {\n' | 798 ' from {\n' |
571 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' | 799 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' |
572 ' }\n' | 800 ' }\n' |
573 ' 10% {\n' | 801 ' 10% {\n' |
574 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' | 802 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' |
575 ' }\n' | 803 ' }\n' |
576 ' 30% {\n' | 804 ' 30% {\n' |
577 ' -webkit-transform: translate3d(0, 2, 0) scale(1.0);\n' | 805 ' -webkit-transform: translate3d(0, 2, 0) scale(1.0);\n' |
578 ' }\n' | 806 ' }\n' |
579 '}\n' | 807 '}\n' |
580 '.foobar {\n' | 808 '.foobar {\n' |
581 ' grid-columns: 10px ("content" 1fr 10px) [4];\n' | 809 ' grid-columns: 10px ("content" 1fr 10px) [4];\n' |
582 '}\n' | 810 '}\n' |
583 '.test-background {\n' | 811 '.test-background {\n' |
584 ' background: url("http://www.foo.com/bar.png");\n' | 812 ' background: url("http://www.foo.com/bar.png");\n' |
| 813 '}\n' |
| 814 '.test-background-with-multiple-properties {\n' |
| 815 ' background: #000 url("http://www.foo.com/bar.png");\n' |
585 '}'; | 816 '}'; |
586 var stylesheet = parseCss(input, errors: errors); | 817 var stylesheet = parseCss(input, errors: errors); |
587 | 818 |
588 expect(stylesheet != null, true); | 819 expect(stylesheet != null, true); |
589 expect(errors.isEmpty, true, reason: errors.toString()); | 820 expect(errors.isEmpty, true, reason: errors.toString()); |
590 expect(prettyPrint(stylesheet), generated); | 821 expect(prettyPrint(stylesheet), generated); |
591 } | 822 } |
592 | 823 |
593 void testCompactEmitter() { | 824 void testCompactEmitter() { |
594 var errors = []; | 825 var errors = <Message>[]; |
595 | 826 |
596 // Check !import compactly emitted. | 827 // Check !import compactly emitted. |
597 final String input = r''' | 828 final String input = r''' |
598 div { | 829 div { |
599 color: green !important; | 830 color: green !important; |
600 } | 831 } |
601 '''; | 832 '''; |
602 final String generated = "div { color: green!important; }"; | 833 final String generated = "div { color:green!important; }"; |
603 | 834 |
604 var stylesheet = parseCss(input, errors: errors); | 835 var stylesheet = parseCss(input, errors: errors); |
605 | 836 |
606 expect(stylesheet != null, true); | 837 expect(stylesheet != null, true); |
607 expect(errors.isEmpty, true, reason: errors.toString()); | 838 expect(errors.isEmpty, true, reason: errors.toString()); |
608 expect(compactOuptut(stylesheet), generated); | 839 expect(compactOuptut(stylesheet), generated); |
609 | 840 |
610 // Check namespace directive compactly emitted. | 841 // Check namespace directive compactly emitted. |
611 final String input2 = "@namespace a url(http://www.example.org/a);"; | 842 final String input2 = "@namespace a url(http://www.example.org/a);"; |
612 final String generated2 = "@namespace a url(http://www.example.org/a);"; | 843 final String generated2 = "@namespace a url(http://www.example.org/a);"; |
613 | 844 |
614 var stylesheet2 = parseCss(input2, errors: errors..clear()); | 845 var stylesheet2 = parseCss(input2, errors: errors..clear()); |
615 | 846 |
616 expect(stylesheet2 != null, true); | 847 expect(stylesheet2 != null, true); |
617 expect(errors.isEmpty, true, reason: errors.toString()); | 848 expect(errors.isEmpty, true, reason: errors.toString()); |
618 expect(compactOuptut(stylesheet2), generated2); | 849 expect(compactOuptut(stylesheet2), generated2); |
619 } | 850 } |
620 | 851 |
621 void testNotSelectors() { | 852 void testNotSelectors() { |
622 var errors = []; | 853 var errors = <Message>[]; |
623 | 854 |
624 final String input = r''' | 855 final String input = r''' |
625 .details:not(.open-details) x-element, | 856 .details:not(.open-details) x-element, |
626 .details:not(.open-details) .summary { | 857 .details:not(.open-details) .summary { |
627 overflow: hidden; | 858 overflow: hidden; |
628 } | 859 } |
629 | 860 |
630 .details:not(.open-details) x-icon { | 861 .details:not(.open-details) x-icon { |
631 margin-left: 99px; | 862 margin-left: 99px; |
632 } | 863 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 }'''; | 933 }'''; |
703 | 934 |
704 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); | 935 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
705 | 936 |
706 expect(stylesheet != null, true); | 937 expect(stylesheet != null, true); |
707 expect(errors.isEmpty, true, reason: errors.toString()); | 938 expect(errors.isEmpty, true, reason: errors.toString()); |
708 expect(prettyPrint(stylesheet), generated); | 939 expect(prettyPrint(stylesheet), generated); |
709 } | 940 } |
710 | 941 |
711 void testIE() { | 942 void testIE() { |
712 var errors = []; | 943 var errors = <Message>[]; |
713 final String input = ".test {\n" | 944 final String input = ".test {\n" |
714 " filter: progid:DXImageTransform.Microsoft.gradient" | 945 " filter: progid:DXImageTransform.Microsoft.gradient" |
715 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" | 946 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" |
716 "}"; | 947 "}"; |
717 final String generated = ".test {\n" | 948 final String generated = ".test {\n" |
718 " filter: progid:DXImageTransform.Microsoft.gradient" | 949 " filter: progid:DXImageTransform.Microsoft.gradient" |
719 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" | 950 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" |
720 "}"; | 951 "}"; |
721 | 952 |
722 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); | 953 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 ' Filter: Alpha(Opacity=100, FinishOpacity=0, Style=2, ' | 996 ' Filter: Alpha(Opacity=100, FinishOpacity=0, Style=2, ' |
766 'StartX=20, StartY=40,\n' | 997 'StartX=20, StartY=40,\n' |
767 ' FinishX=0, FinishY=0) Wave(Add=0, Freq=5, LightStrength=20,\n' | 998 ' FinishX=0, FinishY=0) Wave(Add=0, Freq=5, LightStrength=20,\n' |
768 ' Phase=220, Strength=10);\n}'; | 999 ' Phase=220, Strength=10);\n}'; |
769 | 1000 |
770 stylesheet = parseCss(input3, errors: errors..clear(), opts: simpleOptions); | 1001 stylesheet = parseCss(input3, errors: errors..clear(), opts: simpleOptions); |
771 | 1002 |
772 expect(stylesheet != null, true); | 1003 expect(stylesheet != null, true); |
773 expect(errors.isEmpty, true, reason: errors.toString()); | 1004 expect(errors.isEmpty, true, reason: errors.toString()); |
774 expect(prettyPrint(stylesheet), generated3); | 1005 expect(prettyPrint(stylesheet), generated3); |
| 1006 |
| 1007 final input4 = ''' |
| 1008 div { |
| 1009 filter: FlipH; |
| 1010 }'''; |
| 1011 |
| 1012 stylesheet = parseCss(input4, errors: errors..clear(), opts: simpleOptions); |
| 1013 |
| 1014 expect(stylesheet != null, true); |
| 1015 expect(errors.isEmpty, true, reason: errors.toString()); |
| 1016 expect(prettyPrint(stylesheet), input4); |
775 } | 1017 } |
776 | 1018 |
777 /** | 1019 /** |
778 * Test IE specific declaration syntax: | 1020 * Test IE specific declaration syntax: |
779 * IE6 property name prefixed with _ (normal CSS property name can start | 1021 * IE6 property name prefixed with _ (normal CSS property name can start |
780 * with an underscore). | 1022 * with an underscore). |
781 * | 1023 * |
782 * IE7 or below property add asterisk before the CSS property. | 1024 * IE7 or below property add asterisk before the CSS property. |
783 * | 1025 * |
784 * IE8 or below add \9 at end of declaration expression e.g., | 1026 * IE8 or below add \9 at end of declaration expression e.g., |
785 * background: red\9; | 1027 * background: red\9; |
786 */ | 1028 */ |
787 void testIEDeclaration() { | 1029 void testIEDeclaration() { |
788 var errors = []; | 1030 var errors = <Message>[]; |
789 | 1031 |
790 final input = ''' | 1032 final input = ''' |
791 .testIE-6 { | 1033 .testIE-6 { |
792 _zoom : 5; | 1034 _zoom : 5; |
793 } | 1035 } |
794 .clearfix { | 1036 .clearfix { |
795 *zoom: 1; | 1037 *zoom: 1; |
796 } | 1038 } |
797 audio, video { | 1039 audio, video { |
798 display: inline-block; | 1040 display: inline-block; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 } | 1186 } |
945 }'''; | 1187 }'''; |
946 | 1188 |
947 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); | 1189 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
948 expect(stylesheet != null, true); | 1190 expect(stylesheet != null, true); |
949 expect(errors.isEmpty, true, reason: errors.toString()); | 1191 expect(errors.isEmpty, true, reason: errors.toString()); |
950 expect(prettyPrint(stylesheet), generated); | 1192 expect(prettyPrint(stylesheet), generated); |
951 } | 1193 } |
952 | 1194 |
953 void testHangs() { | 1195 void testHangs() { |
954 var errors = []; | 1196 var errors = <Message>[]; |
955 | 1197 |
956 // Bad hexvalue had caused a hang in processTerm. | 1198 // Bad hexvalue had caused a hang in processTerm. |
957 final input = r'''#a { color: #ebebeburl(0/IE8+9+); }'''; | 1199 final input = r'''#a { color: #ebebeburl(0/IE8+9+); }'''; |
958 var stylesheet = parseCss(input, errors: errors, opts: options); | 1200 var stylesheet = parseCss(input, errors: errors, opts: options); |
959 | 1201 |
960 expect(stylesheet != null, true); | 1202 expect(stylesheet != null, true); |
961 expect(errors.length, 3, reason: errors.toString()); | 1203 expect(errors.length, 3, reason: errors.toString()); |
962 | 1204 |
963 var errorMessage = errors[0]; | 1205 var errorMessage = errors[0]; |
964 expect(errorMessage.message, contains('Bad hex number')); | 1206 expect(errorMessage.message, contains('Bad hex number')); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 expect(errorMessage.message, contains('unexpected end of file')); | 1243 expect(errorMessage.message, contains('unexpected end of file')); |
1002 expect(errorMessage.span, isNotNull); | 1244 expect(errorMessage.span, isNotNull); |
1003 expect(errorMessage.span.start.line, 7); | 1245 expect(errorMessage.span.start.line, 7); |
1004 expect(errorMessage.span.start.column, 0); | 1246 expect(errorMessage.span.start.column, 0); |
1005 expect(errorMessage.span.text.trim(), ''); | 1247 expect(errorMessage.span.text.trim(), ''); |
1006 } | 1248 } |
1007 | 1249 |
1008 void testExpressionSpans() { | 1250 void testExpressionSpans() { |
1009 final input = r'''.foo { width: 50px; }'''; | 1251 final input = r'''.foo { width: 50px; }'''; |
1010 var stylesheet = parseCss(input); | 1252 var stylesheet = parseCss(input); |
1011 var decl = stylesheet.topLevels.single.declarationGroup.declarations.single; | 1253 var decl = (stylesheet.topLevels.single as RuleSet) |
| 1254 .declarationGroup |
| 1255 .declarations |
| 1256 .single; |
1012 // This passes | 1257 // This passes |
1013 expect(decl.span.text, 'width: 50px'); | 1258 expect(decl.span.text, 'width: 50px'); |
1014 // This currently fails | 1259 // This currently fails |
1015 expect(decl.expression.span.text, '50px'); | 1260 expect((decl as Declaration).expression.span.text, '50px'); |
1016 } | 1261 } |
1017 | 1262 |
1018 void simpleCalc() { | 1263 void simpleCalc() { |
1019 final input = r'''.foo { height: calc(100% - 55px); }'''; | 1264 final input = r'''.foo { height: calc(100% - 55px); }'''; |
1020 var stylesheet = parseCss(input); | 1265 var stylesheet = parseCss(input); |
1021 var decl = stylesheet.topLevels.single.declarationGroup.declarations.single; | 1266 var decl = (stylesheet.topLevels.single as RuleSet) |
| 1267 .declarationGroup |
| 1268 .declarations |
| 1269 .single; |
1022 expect(decl.span.text, 'height: calc(100% - 55px)'); | 1270 expect(decl.span.text, 'height: calc(100% - 55px)'); |
1023 } | 1271 } |
1024 | 1272 |
1025 void complexCalc() { | 1273 void complexCalc() { |
1026 final input = r'''.foo { left: calc((100%/3 - 2) * 1em - 2 * 1px); }'''; | 1274 final input = r'''.foo { left: calc((100%/3 - 2) * 1em - 2 * 1px); }'''; |
1027 var stylesheet = parseCss(input); | 1275 var stylesheet = parseCss(input); |
1028 var decl = stylesheet.topLevels.single.declarationGroup.declarations.single; | 1276 var decl = (stylesheet.topLevels.single as RuleSet) |
| 1277 .declarationGroup |
| 1278 .declarations |
| 1279 .single; |
1029 expect(decl.span.text, 'left: calc((100%/3 - 2) * 1em - 2 * 1px)'); | 1280 expect(decl.span.text, 'left: calc((100%/3 - 2) * 1em - 2 * 1px)'); |
1030 } | 1281 } |
1031 | 1282 |
1032 void twoCalcs() { | 1283 void twoCalcs() { |
1033 final input = r'''.foo { margin: calc(1rem - 2px) calc(1rem - 1px); }'''; | 1284 final input = r'''.foo { margin: calc(1rem - 2px) calc(1rem - 1px); }'''; |
1034 var stylesheet = parseCss(input); | 1285 var stylesheet = parseCss(input); |
1035 var decl = stylesheet.topLevels.single.declarationGroup.declarations.single; | 1286 var decl = (stylesheet.topLevels.single as RuleSet) |
| 1287 .declarationGroup |
| 1288 .declarations |
| 1289 .single; |
1036 expect(decl.span.text, 'margin: calc(1rem - 2px) calc(1rem - 1px)'); | 1290 expect(decl.span.text, 'margin: calc(1rem - 2px) calc(1rem - 1px)'); |
1037 } | 1291 } |
1038 | 1292 |
1039 void selectorWithCalcs() { | 1293 void selectorWithCalcs() { |
1040 var errors = []; | 1294 var errors = <Message>[]; |
1041 final String input = r''' | 1295 final String input = r''' |
1042 .foo { | 1296 .foo { |
1043 width: calc(1em + 5 * 2em); | 1297 width: calc(1em + 5 * 2em); |
1044 height: calc(1px + 2%) !important; | 1298 height: calc(1px + 2%) !important; |
1045 border: 5px calc(1pt + 2cm) 6px calc(1em + 1in + 2px) red; | 1299 border: 5px calc(1pt + 2cm) 6px calc(1em + 1in + 2px) red; |
1046 border: calc(5px + 1em) 0px 1px calc(10 + 20 + 1px); | 1300 border: calc(5px + 1em) 0px 1px calc(10 + 20 + 1px); |
1047 margin: 25px calc(50px + (100% / (3 - 1em) - 20%)) calc(10px + 10 * 20) calc(1
00% - 10px); | 1301 margin: 25px calc(50px + (100% / (3 - 1em) - 20%)) calc(10px + 10 * 20) calc(1
00% - 10px); |
1048 }'''; | 1302 }'''; |
1049 final String generated = r''' | 1303 final String generated = r''' |
1050 .foo { | 1304 .foo { |
1051 width: calc(1em + 5 * 2em); | 1305 width: calc(1em + 5 * 2em); |
1052 height: calc(1px + 2%) !important; | 1306 height: calc(1px + 2%) !important; |
1053 border: 5px calc(1pt + 2cm) 6px calc(1em + 1in + 2px) #f00; | 1307 border: 5px calc(1pt + 2cm) 6px calc(1em + 1in + 2px) #f00; |
1054 border: calc(5px + 1em) 0px 1px calc(10 + 20 + 1px); | 1308 border: calc(5px + 1em) 0px 1px calc(10 + 20 + 1px); |
1055 margin: 25px calc(50px + (100% / (3 - 1em) - 20%)) calc(10px + 10 * 20) calc(1
00% - 10px); | 1309 margin: 25px calc(50px + (100% / (3 - 1em) - 20%)) calc(10px + 10 * 20) calc(1
00% - 10px); |
1056 }'''; | 1310 }'''; |
1057 | 1311 |
1058 var stylesheet = parseCss(input, errors: errors); | 1312 var stylesheet = parseCss(input, errors: errors); |
1059 expect(stylesheet != null, true); | 1313 expect(stylesheet != null, true); |
1060 expect(errors.isEmpty, true, reason: errors.toString()); | 1314 expect(errors.isEmpty, true, reason: errors.toString()); |
1061 expect(prettyPrint(stylesheet), generated); | 1315 expect(prettyPrint(stylesheet), generated); |
1062 } | 1316 } |
1063 | 1317 |
| 1318 void vendorPrefixedCalc() { |
| 1319 var css = ''' |
| 1320 .foo { |
| 1321 width: -webkit-calc((100% - 15px*1) / 1); |
| 1322 }'''; |
| 1323 expectCss(css, css); |
| 1324 |
| 1325 css = ''' |
| 1326 .foo { |
| 1327 width: -moz-calc((100% - 15px*1) / 1); |
| 1328 }'''; |
| 1329 expectCss(css, css); |
| 1330 } |
| 1331 |
1064 main() { | 1332 main() { |
1065 test('Simple Terms', testSimpleTerms); | 1333 test('Simple Terms', testSimpleTerms); |
1066 test('Declarations', testDeclarations); | 1334 test('Declarations', testDeclarations); |
1067 test('Identifiers', testIdentifiers); | 1335 test('Identifiers', testIdentifiers); |
1068 test('Composites', testComposites); | 1336 test('Composites', testComposites); |
1069 test('Units', testUnits); | 1337 test('Units', testUnits); |
1070 test('Unicode', testUnicode); | 1338 test('Unicode', testUnicode); |
1071 test('Newer CSS', testNewerCss); | 1339 test('Newer CSS', testNewerCss); |
1072 test('Media Queries', testMediaQueries); | 1340 test('Media Queries', testMediaQueries); |
| 1341 test('Document', testMozDocument); |
| 1342 test('Supports', testSupports); |
| 1343 test('Viewport', testViewport); |
1073 test('Font-Face', testFontFace); | 1344 test('Font-Face', testFontFace); |
1074 test('CSS file', testCssFile); | 1345 test('CSS file', testCssFile); |
1075 test('Compact Emitter', testCompactEmitter); | 1346 test('Compact Emitter', testCompactEmitter); |
1076 test('Selector Negation', testNotSelectors); | 1347 test('Selector Negation', testNotSelectors); |
1077 test('IE stuff', testIE); | 1348 test('IE stuff', testIE); |
1078 test('IE declaration syntax', testIEDeclaration); | 1349 test('IE declaration syntax', testIEDeclaration); |
1079 test('Hanging bugs', testHangs); | 1350 test('Hanging bugs', testHangs); |
1080 test('Expression spans', testExpressionSpans, | 1351 test('Expression spans', testExpressionSpans, |
1081 skip: 'expression spans are broken' | 1352 skip: 'expression spans are broken' |
1082 ' (https://github.com/dart-lang/csslib/issues/15)'); | 1353 ' (https://github.com/dart-lang/csslib/issues/15)'); |
1083 group('calc function', () { | 1354 group('calc function', () { |
1084 test('simple calc', simpleCalc); | 1355 test('simple calc', simpleCalc); |
1085 test('single complex', complexCalc); | 1356 test('single complex', complexCalc); |
1086 test('two calc terms for same declaration', twoCalcs); | 1357 test('two calc terms for same declaration', twoCalcs); |
1087 test('selector with many calc declarations', selectorWithCalcs); | 1358 test('selector with many calc declarations', selectorWithCalcs); |
| 1359 test('vendor prefixed calc', vendorPrefixedCalc); |
1088 }); | 1360 }); |
1089 } | 1361 } |
1090 | |
OLD | NEW |