OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library declaration_test; |
| 6 |
| 7 import 'package:test/test.dart'; |
| 8 |
| 9 import 'testing.dart'; |
| 10 |
| 11 void testSimpleTerms() { |
| 12 var errors = []; |
| 13 final String input = r''' |
| 14 @ import url("test.css"); |
| 15 .foo { |
| 16 background-color: #191919; |
| 17 width: 10PX; |
| 18 height: 22mM !important; |
| 19 border-width: 20cm; |
| 20 margin-width: 33%; |
| 21 border-height: 30EM; |
| 22 width: .6in; |
| 23 length: 1.2in; |
| 24 -web-stuff: -10Px; |
| 25 }'''; |
| 26 final String generated = r''' |
| 27 @import "test.css"; |
| 28 .foo { |
| 29 background-color: #191919; |
| 30 width: 10px; |
| 31 height: 22mm !important; |
| 32 border-width: 20cm; |
| 33 margin-width: 33%; |
| 34 border-height: 30em; |
| 35 width: .6in; |
| 36 length: 1.2in; |
| 37 -web-stuff: -10px; |
| 38 }'''; |
| 39 |
| 40 var stylesheet = parseCss(input, errors: errors); |
| 41 |
| 42 expect(stylesheet != null, true); |
| 43 expect(errors.isEmpty, true, reason: errors.toString()); |
| 44 expect(prettyPrint(stylesheet), generated); |
| 45 |
| 46 final String input2 = r''' |
| 47 * { |
| 48 border-color: green; |
| 49 }'''; |
| 50 final String generated2 = r''' |
| 51 * { |
| 52 border-color: #008000; |
| 53 }'''; |
| 54 |
| 55 stylesheet = parseCss(input2, errors: errors..clear()); |
| 56 |
| 57 expect(stylesheet != null, true); |
| 58 expect(errors.isEmpty, true, reason: errors.toString()); |
| 59 expect(prettyPrint(stylesheet), generated2); |
| 60 } |
| 61 |
| 62 /** |
| 63 * Declarations with comments, references with single-quotes, double-quotes, |
| 64 * no quotes. Hex values with # and letters, and functions (rgba, url, etc.) |
| 65 */ |
| 66 void testDeclarations() { |
| 67 var errors = []; |
| 68 final String input = r''' |
| 69 .more { |
| 70 color: white; |
| 71 color: black; |
| 72 color: cyan; |
| 73 color: red; |
| 74 color: #aabbcc; /* test -- 3 */ |
| 75 color: blue; |
| 76 background-image: url(http://test.jpeg); |
| 77 background-image: url("http://double_quote.html"); |
| 78 background-image: url('http://single_quote.html'); |
| 79 color: rgba(10,20,255); <!-- test CDO/CDC --> |
| 80 color: #123aef; /* hex # part integer and part identifier */ |
| 81 }'''; |
| 82 final String generated = r''' |
| 83 .more { |
| 84 color: #fff; |
| 85 color: #000; |
| 86 color: #0ff; |
| 87 color: #f00; |
| 88 color: #abc; |
| 89 color: #00f; |
| 90 background-image: url("http://test.jpeg"); |
| 91 background-image: url("http://double_quote.html"); |
| 92 background-image: url("http://single_quote.html"); |
| 93 color: rgba(10, 20, 255); |
| 94 color: #123aef; |
| 95 }'''; |
| 96 |
| 97 var stylesheet = parseCss(input, errors: errors); |
| 98 |
| 99 expect(stylesheet != null, true); |
| 100 expect(errors.isEmpty, true, reason: errors.toString()); |
| 101 expect(prettyPrint(stylesheet), generated); |
| 102 } |
| 103 |
| 104 void testIdentifiers() { |
| 105 var errors = []; |
| 106 final String input = r''' |
| 107 #da { |
| 108 height: 100px; |
| 109 } |
| 110 #foo { |
| 111 width: 10px; |
| 112 color: #ff00cc; |
| 113 } |
| 114 '''; |
| 115 final String generated = r''' |
| 116 #da { |
| 117 height: 100px; |
| 118 } |
| 119 #foo { |
| 120 width: 10px; |
| 121 color: #f0c; |
| 122 }'''; |
| 123 |
| 124 var stylesheet = parseCss(input, errors: errors); |
| 125 |
| 126 expect(errors.isEmpty, true, reason: errors.toString()); |
| 127 expect(stylesheet != null, true); |
| 128 expect(prettyPrint(stylesheet), generated); |
| 129 } |
| 130 |
| 131 void testComposites() { |
| 132 var errors = []; |
| 133 final String input = r''' |
| 134 .xyzzy { |
| 135 border: 10px 80px 90px 100px; |
| 136 width: 99%; |
| 137 } |
| 138 @-webkit-keyframes pulsate { |
| 139 0% { |
| 140 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
| 141 } |
| 142 }'''; |
| 143 final String generated = r''' |
| 144 .xyzzy { |
| 145 border: 10px 80px 90px 100px; |
| 146 width: 99%; |
| 147 } |
| 148 @-webkit-keyframes pulsate { |
| 149 0% { |
| 150 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
| 151 } |
| 152 }'''; |
| 153 |
| 154 var stylesheet = parseCss(input, errors: errors); |
| 155 expect(stylesheet != null, true); |
| 156 expect(errors.isEmpty, true, reason: errors.toString()); |
| 157 expect(prettyPrint(stylesheet), generated); |
| 158 } |
| 159 |
| 160 void testUnits() { |
| 161 var errors = []; |
| 162 final String input = r''' |
| 163 #id-1 { |
| 164 transition: color 0.4s; |
| 165 animation-duration: 500ms; |
| 166 top: 1em; |
| 167 left: 200ex; |
| 168 right: 300px; |
| 169 bottom: 400cm; |
| 170 border-width: 2.5mm; |
| 171 margin-top: .5in; |
| 172 margin-left: 5pc; |
| 173 margin-right: 5ex; |
| 174 margin-bottom: 5ch; |
| 175 font-size: 10pt; |
| 176 padding-top: 22rem; |
| 177 padding-left: 33vw; |
| 178 padding-right: 34vh; |
| 179 padding-bottom: 3vmin; |
| 180 transform: rotate(20deg); |
| 181 voice-pitch: 10hz; |
| 182 } |
| 183 #id-2 { |
| 184 left: 2fr; |
| 185 font-size: 10vmax; |
| 186 transform: rotatex(20rad); |
| 187 voice-pitch: 10khz; |
| 188 -web-kit-resolution: 2dpi; /* Bogus property name testing dpi unit. */ |
| 189 } |
| 190 #id-3 { |
| 191 -web-kit-resolution: 3dpcm; /* Bogus property name testing dpi unit. */ |
| 192 transform: rotatey(20grad); |
| 193 } |
| 194 #id-4 { |
| 195 -web-kit-resolution: 4dppx; /* Bogus property name testing dpi unit. */ |
| 196 transform: rotatez(20turn); |
| 197 } |
| 198 '''; |
| 199 |
| 200 final String generated = r''' |
| 201 #id-1 { |
| 202 transition: color 0.4s; |
| 203 animation-duration: 500ms; |
| 204 top: 1em; |
| 205 left: 200ex; |
| 206 right: 300px; |
| 207 bottom: 400cm; |
| 208 border-width: 2.5mm; |
| 209 margin-top: .5in; |
| 210 margin-left: 5pc; |
| 211 margin-right: 5ex; |
| 212 margin-bottom: 5ch; |
| 213 font-size: 10pt; |
| 214 padding-top: 22rem; |
| 215 padding-left: 33vw; |
| 216 padding-right: 34vh; |
| 217 padding-bottom: 3vmin; |
| 218 transform: rotate(20deg); |
| 219 voice-pitch: 10hz; |
| 220 } |
| 221 #id-2 { |
| 222 left: 2fr; |
| 223 font-size: 10vmax; |
| 224 transform: rotatex(20rad); |
| 225 voice-pitch: 10khz; |
| 226 -web-kit-resolution: 2dpi; |
| 227 } |
| 228 #id-3 { |
| 229 -web-kit-resolution: 3dpcm; |
| 230 transform: rotatey(20grad); |
| 231 } |
| 232 #id-4 { |
| 233 -web-kit-resolution: 4dppx; |
| 234 transform: rotatez(20turn); |
| 235 }'''; |
| 236 |
| 237 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 238 |
| 239 expect(stylesheet != null, true); |
| 240 expect(errors.isEmpty, true, reason: errors.toString()); |
| 241 expect(prettyPrint(stylesheet), generated); |
| 242 } |
| 243 |
| 244 void testUnicode() { |
| 245 var errors = []; |
| 246 final String input = r''' |
| 247 .toggle:after { |
| 248 content: '✔'; |
| 249 line-height: 43px; |
| 250 font-size: 20px; |
| 251 color: #d9d9d9; |
| 252 text-shadow: 0 -1px 0 #bfbfbf; |
| 253 } |
| 254 '''; |
| 255 |
| 256 final String generated = r''' |
| 257 .toggle:after { |
| 258 content: '✔'; |
| 259 line-height: 43px; |
| 260 font-size: 20px; |
| 261 color: #d9d9d9; |
| 262 text-shadow: 0 -1px 0 #bfbfbf; |
| 263 }'''; |
| 264 |
| 265 var stylesheet = parseCss(input, errors: errors); |
| 266 |
| 267 expect(stylesheet != null, true); |
| 268 expect(errors.isEmpty, true, reason: errors.toString()); |
| 269 expect(prettyPrint(stylesheet), generated); |
| 270 } |
| 271 |
| 272 void testNewerCss() { |
| 273 var errors = []; |
| 274 final String input = r''' |
| 275 @media screen,print { |
| 276 .foobar_screen { |
| 277 width: 10px; |
| 278 } |
| 279 } |
| 280 @page { |
| 281 height: 22px; |
| 282 size: 3in 3in; |
| 283 } |
| 284 @page : left { |
| 285 width: 10px; |
| 286 } |
| 287 @page bar : left { @top-left { margin: 8px; } } |
| 288 @charset "ISO-8859-1"; |
| 289 @charset 'ASCII';'''; |
| 290 |
| 291 final String generated = r''' |
| 292 @media screen, print { |
| 293 .foobar_screen { |
| 294 width: 10px; |
| 295 } |
| 296 } |
| 297 @page { |
| 298 height: 22px; |
| 299 size: 3in 3in; |
| 300 } |
| 301 @page:left { |
| 302 width: 10px; |
| 303 } |
| 304 @page bar:left { |
| 305 @top-left { |
| 306 margin: 8px; |
| 307 } |
| 308 } |
| 309 @charset "ISO-8859-1"; |
| 310 @charset "ASCII";'''; |
| 311 |
| 312 var stylesheet = parseCss(input, errors: errors); |
| 313 |
| 314 expect(stylesheet != null, true); |
| 315 expect(errors.isEmpty, true, reason: errors.toString()); |
| 316 expect(prettyPrint(stylesheet), generated); |
| 317 } |
| 318 |
| 319 void testMediaQueries() { |
| 320 var errors = []; |
| 321 String input = ''' |
| 322 @media screen and (-webkit-min-device-pixel-ratio:0) { |
| 323 .todo-item .toggle { |
| 324 background: none; |
| 325 } |
| 326 #todo-item .toggle { |
| 327 height: 40px; |
| 328 } |
| 329 }'''; |
| 330 String generated = ''' |
| 331 @media screen AND (-webkit-min-device-pixel-ratio:0) { |
| 332 .todo-item .toggle { |
| 333 background: none; |
| 334 } |
| 335 #todo-item .toggle { |
| 336 height: 40px; |
| 337 } |
| 338 }'''; |
| 339 |
| 340 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 341 expect(stylesheet != null, true); |
| 342 expect(errors.isEmpty, true, reason: errors.toString()); |
| 343 expect(prettyPrint(stylesheet), generated); |
| 344 |
| 345 input = ''' |
| 346 @media handheld and (min-width: 20em), |
| 347 screen and (min-width: 20em) { |
| 348 #id { color: red; } |
| 349 .myclass { height: 20px; } |
| 350 } |
| 351 @media print and (min-resolution: 300dpi) { |
| 352 #anotherId { |
| 353 color: #fff; |
| 354 } |
| 355 } |
| 356 @media print and (min-resolution: 280dpcm) { |
| 357 #finalId { |
| 358 color: #aaa; |
| 359 } |
| 360 .class2 { |
| 361 border: 20px; |
| 362 } |
| 363 }'''; |
| 364 generated = |
| 365 '''@media handheld AND (min-width:20em), screen AND (min-width:20em) { |
| 366 #id { |
| 367 color: #f00; |
| 368 } |
| 369 .myclass { |
| 370 height: 20px; |
| 371 } |
| 372 } @media print AND (min-resolution:300dpi) { |
| 373 #anotherId { |
| 374 color: #fff; |
| 375 } |
| 376 } @media print AND (min-resolution:280dpcm) { |
| 377 #finalId { |
| 378 color: #aaa; |
| 379 } |
| 380 .class2 { |
| 381 border: 20px; |
| 382 } |
| 383 }'''; |
| 384 |
| 385 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
| 386 |
| 387 expect(stylesheet != null, true); |
| 388 expect(errors.isEmpty, true, reason: errors.toString()); |
| 389 expect(prettyPrint(stylesheet), generated); |
| 390 |
| 391 input = ''' |
| 392 @media only screen and (min-device-width: 4000px) and |
| 393 (min-device-height: 2000px), screen (another: 100px) { |
| 394 html { |
| 395 font-size: 10em; |
| 396 } |
| 397 }'''; |
| 398 generated = '@media ONLY screen AND (min-device-width:4000px) ' |
| 399 'AND (min-device-height:2000px), screen (another:100px) {\n' |
| 400 'html {\n font-size: 10em;\n}\n}'; |
| 401 |
| 402 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
| 403 |
| 404 expect(stylesheet != null, true); |
| 405 expect(errors.isEmpty, true, reason: errors.toString()); |
| 406 expect(prettyPrint(stylesheet), generated); |
| 407 |
| 408 input = ''' |
| 409 @media screen,print (min-device-width: 4000px) and |
| 410 (min-device-height: 2000px), screen (another: 100px) { |
| 411 html { |
| 412 font-size: 10em; |
| 413 } |
| 414 }'''; |
| 415 generated = '@media screen, print (min-device-width:4000px) AND ' |
| 416 '(min-device-height:2000px), screen (another:100px) {\n' |
| 417 'html {\n font-size: 10em;\n}\n}'; |
| 418 |
| 419 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
| 420 |
| 421 expect(stylesheet != null, true); |
| 422 expect(errors.isEmpty, true, reason: errors.toString()); |
| 423 expect(prettyPrint(stylesheet), generated); |
| 424 |
| 425 input = ''' |
| 426 @import "test.css" ONLY screen, NOT print (min-device-width: 4000px);'''; |
| 427 generated = |
| 428 '@import "test.css" ONLY screen, NOT print (min-device-width:4000px);'; |
| 429 |
| 430 stylesheet = parseCss(input, errors: errors..clear(), opts: simpleOptions); |
| 431 |
| 432 expect(stylesheet != null, true); |
| 433 expect(errors.isEmpty, true, reason: errors.toString()); |
| 434 expect(prettyPrint(stylesheet), generated); |
| 435 } |
| 436 |
| 437 void testFontFace() { |
| 438 var errors = []; |
| 439 |
| 440 final String input = ''' |
| 441 @font-face { |
| 442 font-family: BBCBengali; |
| 443 src: url(fonts/BBCBengali.ttf) format("opentype"); |
| 444 unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???; |
| 445 }'''; |
| 446 final String generated = '''@font-face { |
| 447 font-family: BBCBengali; |
| 448 src: url("fonts/BBCBengali.ttf") format("opentype"); |
| 449 unicode-range: U+0A-FF, U+980-9FF, U+????, U+3???; |
| 450 }'''; |
| 451 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 452 |
| 453 expect(stylesheet != null, true); |
| 454 expect(errors.isEmpty, true, reason: errors.toString()); |
| 455 expect(prettyPrint(stylesheet), generated); |
| 456 |
| 457 final String input1 = ''' |
| 458 @font-face { |
| 459 font-family: Gentium; |
| 460 src: url(http://example.com/fonts/Gentium.ttf); |
| 461 src: url(http://example.com/fonts/Gentium.ttf); |
| 462 }'''; |
| 463 final String generated1 = '''@font-face { |
| 464 font-family: Gentium; |
| 465 src: url("http://example.com/fonts/Gentium.ttf"); |
| 466 src: url("http://example.com/fonts/Gentium.ttf"); |
| 467 }'''; |
| 468 |
| 469 stylesheet = parseCss(input1, errors: errors..clear(), opts: simpleOptions); |
| 470 |
| 471 expect(stylesheet != null, true); |
| 472 expect(errors.isEmpty, true, reason: errors.toString()); |
| 473 expect(prettyPrint(stylesheet), generated1); |
| 474 |
| 475 final String input2 = ''' |
| 476 @font-face { |
| 477 src: url(ideal-sans-serif.woff) format("woff"), |
| 478 url(basic-sans-serif.ttf) format("opentype"), |
| 479 local(Gentium Bold); |
| 480 }'''; |
| 481 final String generated2 = '@font-face {\n' |
| 482 ' src: url("ideal-sans-serif.woff") ' |
| 483 'format("woff"), url("basic-sans-serif.ttf") ' |
| 484 'format("opentype"), local(Gentium Bold);\n}'; |
| 485 |
| 486 stylesheet = parseCss(input2, errors: errors..clear(), opts: simpleOptions); |
| 487 |
| 488 expect(stylesheet != null, true); |
| 489 expect(errors.isEmpty, true, reason: errors.toString()); |
| 490 expect(prettyPrint(stylesheet), generated2); |
| 491 |
| 492 final String input3 = '''@font-face { |
| 493 font-family: MyGentium Text Ornaments; |
| 494 src: local(Gentium Bold), /* full font name */ |
| 495 local(Gentium-Bold), /* Postscript name */ |
| 496 url(GentiumBold.ttf); /* otherwise, download it */ |
| 497 font-weight: bold; |
| 498 }'''; |
| 499 final String generated3 = '''@font-face { |
| 500 font-family: MyGentium Text Ornaments; |
| 501 src: local(Gentium Bold), local(Gentium-Bold), url("GentiumBold.ttf"); |
| 502 font-weight: bold; |
| 503 }'''; |
| 504 |
| 505 stylesheet = parseCss(input3, errors: errors..clear(), opts: simpleOptions); |
| 506 |
| 507 expect(stylesheet != null, true); |
| 508 expect(errors.isEmpty, true, reason: errors.toString()); |
| 509 expect(prettyPrint(stylesheet), generated3); |
| 510 |
| 511 final String input4 = ''' |
| 512 @font-face { |
| 513 font-family: STIXGeneral; |
| 514 src: local(STIXGeneral), url(/stixfonts/STIXGeneral.otf); |
| 515 unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF; |
| 516 }'''; |
| 517 final String generated4 = '''@font-face { |
| 518 font-family: STIXGeneral; |
| 519 src: local(STIXGeneral), url("/stixfonts/STIXGeneral.otf"); |
| 520 unicode-range: U+000-49F, U+2000-27FF, U+2900-2BFF, U+1D400-1D7FF; |
| 521 }'''; |
| 522 stylesheet = parseCss(input4, errors: errors..clear(), opts: simpleOptions); |
| 523 |
| 524 expect(stylesheet != null, true); |
| 525 expect(errors.isEmpty, true, reason: errors.toString()); |
| 526 expect(prettyPrint(stylesheet), generated4); |
| 527 } |
| 528 |
| 529 void testCssFile() { |
| 530 var errors = []; |
| 531 final String input = r''' |
| 532 @import 'simple.css' |
| 533 @import "test.css" print |
| 534 @import url(test.css) screen, print |
| 535 @import url(http://google.com/maps/maps.css); |
| 536 |
| 537 div[href^='test'] { |
| 538 height: 10px; |
| 539 } |
| 540 |
| 541 @-webkit-keyframes pulsate { |
| 542 from { |
| 543 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
| 544 } |
| 545 10% { |
| 546 -webkit-transform: translate3d(0, 0, 0) scale(1.0); |
| 547 } |
| 548 30% { |
| 549 -webkit-transform: translate3d(0, 2, 0) scale(1.0); |
| 550 } |
| 551 } |
| 552 |
| 553 .foobar { |
| 554 grid-columns: 10px ("content" 1fr 10px)[4]; |
| 555 } |
| 556 |
| 557 .test-background { |
| 558 background: url(http://www.foo.com/bar.png); |
| 559 } |
| 560 '''; |
| 561 |
| 562 final String generated = '@import "simple.css"; ' |
| 563 '@import "test.css" print; ' |
| 564 '@import "test.css" screen, print; ' |
| 565 '@import "http://google.com/maps/maps.css";\n' |
| 566 'div[href^="test"] {\n' |
| 567 ' height: 10px;\n' |
| 568 '}\n' |
| 569 '@-webkit-keyframes pulsate {\n' |
| 570 ' from {\n' |
| 571 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' |
| 572 ' }\n' |
| 573 ' 10% {\n' |
| 574 ' -webkit-transform: translate3d(0, 0, 0) scale(1.0);\n' |
| 575 ' }\n' |
| 576 ' 30% {\n' |
| 577 ' -webkit-transform: translate3d(0, 2, 0) scale(1.0);\n' |
| 578 ' }\n' |
| 579 '}\n' |
| 580 '.foobar {\n' |
| 581 ' grid-columns: 10px ("content" 1fr 10px) [4];\n' |
| 582 '}\n' |
| 583 '.test-background {\n' |
| 584 ' background: url("http://www.foo.com/bar.png");\n' |
| 585 '}'; |
| 586 var stylesheet = parseCss(input, errors: errors); |
| 587 |
| 588 expect(stylesheet != null, true); |
| 589 expect(errors.isEmpty, true, reason: errors.toString()); |
| 590 expect(prettyPrint(stylesheet), generated); |
| 591 } |
| 592 |
| 593 void testCompactEmitter() { |
| 594 var errors = []; |
| 595 |
| 596 // Check !import compactly emitted. |
| 597 final String input = r''' |
| 598 div { |
| 599 color: green !important; |
| 600 } |
| 601 '''; |
| 602 final String generated = "div { color: green!important; }"; |
| 603 |
| 604 var stylesheet = parseCss(input, errors: errors); |
| 605 |
| 606 expect(stylesheet != null, true); |
| 607 expect(errors.isEmpty, true, reason: errors.toString()); |
| 608 expect(compactOuptut(stylesheet), generated); |
| 609 |
| 610 // Check namespace directive compactly emitted. |
| 611 final String input2 = "@namespace a url(http://www.example.org/a);"; |
| 612 final String generated2 = "@namespace a url(http://www.example.org/a);"; |
| 613 |
| 614 var stylesheet2 = parseCss(input2, errors: errors..clear()); |
| 615 |
| 616 expect(stylesheet2 != null, true); |
| 617 expect(errors.isEmpty, true, reason: errors.toString()); |
| 618 expect(compactOuptut(stylesheet2), generated2); |
| 619 } |
| 620 |
| 621 void testNotSelectors() { |
| 622 var errors = []; |
| 623 |
| 624 final String input = r''' |
| 625 .details:not(.open-details) x-element, |
| 626 .details:not(.open-details) .summary { |
| 627 overflow: hidden; |
| 628 } |
| 629 |
| 630 .details:not(.open-details) x-icon { |
| 631 margin-left: 99px; |
| 632 } |
| 633 |
| 634 .kind-class .details:not(.open-details) x-icon { |
| 635 margin-left: 0px; |
| 636 } |
| 637 |
| 638 .name { |
| 639 margin-left: 0px; |
| 640 } |
| 641 |
| 642 .details:not(.open-details) .the-class { |
| 643 width: 80px; |
| 644 } |
| 645 |
| 646 *:focus |
| 647 { |
| 648 outline: none; |
| 649 } |
| 650 |
| 651 body > h2:not(:first-of-type):not(:last-of-type) { |
| 652 color: red; |
| 653 } |
| 654 |
| 655 .details-1:not([DISABLED]) { |
| 656 outline: none; |
| 657 } |
| 658 |
| 659 html|*:not(:link):not(:visited) { |
| 660 width: 92%; |
| 661 } |
| 662 |
| 663 *|*:not(*) { |
| 664 font-weight: bold; |
| 665 } |
| 666 |
| 667 *:not(:not([disabled])) { color: blue; } |
| 668 '''; |
| 669 final String generated = r''' |
| 670 .details:not(.open-details) x-element, .details:not(.open-details) .summary { |
| 671 overflow: hidden; |
| 672 } |
| 673 .details:not(.open-details) x-icon { |
| 674 margin-left: 99px; |
| 675 } |
| 676 .kind-class .details:not(.open-details) x-icon { |
| 677 margin-left: 0px; |
| 678 } |
| 679 .name { |
| 680 margin-left: 0px; |
| 681 } |
| 682 .details:not(.open-details) .the-class { |
| 683 width: 80px; |
| 684 } |
| 685 *:focus { |
| 686 outline: none; |
| 687 } |
| 688 body > h2:not(:first-of-type):not(:last-of-type) { |
| 689 color: #f00; |
| 690 } |
| 691 .details-1:not([DISABLED]) { |
| 692 outline: none; |
| 693 } |
| 694 html|*:not(:link):not(:visited) { |
| 695 width: 92%; |
| 696 } |
| 697 *|*:not(*) { |
| 698 font-weight: bold; |
| 699 } |
| 700 *:not(:not([disabled])) { |
| 701 color: #00f; |
| 702 }'''; |
| 703 |
| 704 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 705 |
| 706 expect(stylesheet != null, true); |
| 707 expect(errors.isEmpty, true, reason: errors.toString()); |
| 708 expect(prettyPrint(stylesheet), generated); |
| 709 } |
| 710 |
| 711 void testIE() { |
| 712 var errors = []; |
| 713 final String input = ".test {\n" |
| 714 " filter: progid:DXImageTransform.Microsoft.gradient" |
| 715 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" |
| 716 "}"; |
| 717 final String generated = ".test {\n" |
| 718 " filter: progid:DXImageTransform.Microsoft.gradient" |
| 719 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n" |
| 720 "}"; |
| 721 |
| 722 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 723 |
| 724 expect(stylesheet != null, true); |
| 725 expect(errors.isEmpty, true, reason: errors.toString()); |
| 726 expect(prettyPrint(stylesheet), generated); |
| 727 |
| 728 final String input2 = ".test {\n" |
| 729 " filter: progid:DXImageTransform.Microsoft.gradient" |
| 730 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670')\n" |
| 731 " progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1
);\n" |
| 732 "}"; |
| 733 |
| 734 final String generated2 = ".test {\n" |
| 735 " filter: progid:DXImageTransform.Microsoft.gradient" |
| 736 "(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670')\n" |
| 737 " progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=
1);\n" |
| 738 "}"; |
| 739 |
| 740 stylesheet = parseCss(input2, errors: errors..clear(), opts: simpleOptions); |
| 741 |
| 742 expect(stylesheet != null, true); |
| 743 expect(errors.isEmpty, true, reason: errors.toString()); |
| 744 expect(prettyPrint(stylesheet), generated2); |
| 745 |
| 746 final String input3 = ''' |
| 747 div { |
| 748 filter: alpha(opacity=80); /* IE7 and under */ |
| 749 -ms-filter: "Alpha(Opacity=40)"; /* IE8 and newer */ |
| 750 |
| 751 Filter: Blur(Add = 0, Direction = 225, Strength = 10); |
| 752 Filter: FlipV; |
| 753 Filter: Gray; |
| 754 FILTER: Chroma(Color = #000000) Mask(Color=#00FF00); |
| 755 Filter: Alpha(Opacity=100, FinishOpacity=0, Style=2, StartX=20, StartY=40, |
| 756 FinishX=0, FinishY=0) Wave(Add=0, Freq=5, LightStrength=20, |
| 757 Phase=220, Strength=10); |
| 758 } |
| 759 '''; |
| 760 final String generated3 = 'div {\n filter: alpha(opacity=80);\n' |
| 761 ' -ms-filter: "Alpha(Opacity=40)";\n' |
| 762 ' Filter: Blur(Add = 0, Direction = 225, Strength = 10);\n' |
| 763 ' Filter: FlipV;\n Filter: Gray;\n' |
| 764 ' FILTER: Chroma(Color = #000000) Mask(Color=#00FF00);\n' |
| 765 ' Filter: Alpha(Opacity=100, FinishOpacity=0, Style=2, ' |
| 766 'StartX=20, StartY=40,\n' |
| 767 ' FinishX=0, FinishY=0) Wave(Add=0, Freq=5, LightStrength=20,\n' |
| 768 ' Phase=220, Strength=10);\n}'; |
| 769 |
| 770 stylesheet = parseCss(input3, errors: errors..clear(), opts: simpleOptions); |
| 771 |
| 772 expect(stylesheet != null, true); |
| 773 expect(errors.isEmpty, true, reason: errors.toString()); |
| 774 expect(prettyPrint(stylesheet), generated3); |
| 775 } |
| 776 |
| 777 /** |
| 778 * Test IE specific declaration syntax: |
| 779 * IE6 property name prefixed with _ (normal CSS property name can start |
| 780 * with an underscore). |
| 781 * |
| 782 * IE7 or below property add asterisk before the CSS property. |
| 783 * |
| 784 * IE8 or below add \9 at end of declaration expression e.g., |
| 785 * background: red\9; |
| 786 */ |
| 787 void testIEDeclaration() { |
| 788 var errors = []; |
| 789 |
| 790 final input = ''' |
| 791 .testIE-6 { |
| 792 _zoom : 5; |
| 793 } |
| 794 .clearfix { |
| 795 *zoom: 1; |
| 796 } |
| 797 audio, video { |
| 798 display: inline-block; |
| 799 *display: inline; |
| 800 *zoom: 1; |
| 801 } |
| 802 input { |
| 803 *overflow: visible; |
| 804 line-height: normal; |
| 805 } |
| 806 .uneditable-input:focus { |
| 807 border-color: rgba(82, 168, 236, 0.8); |
| 808 outline: 0; |
| 809 outline: thin dotted \\9; /* IE6-9 */ |
| 810 } |
| 811 |
| 812 input[type="radio"], input[type="checkbox"] { |
| 813 margin-top: 1px \\9; |
| 814 *margin-top: 0; |
| 815 } |
| 816 |
| 817 input.search-query { |
| 818 padding-right: 14px; |
| 819 padding-right: 4px \\9; |
| 820 padding-left: 14px; |
| 821 padding-left: 4px \\9; /* IE7-8 no border-radius, don't indent padding. */ |
| 822 } |
| 823 |
| 824 .btn.active { |
| 825 background-color: #cccccc \\9; |
| 826 } |
| 827 |
| 828 @-webkit-keyframes progress-bar-stripes { |
| 829 from { |
| 830 background-position: 40px 0; |
| 831 } |
| 832 to { |
| 833 background-position: 0 0; |
| 834 } |
| 835 } |
| 836 |
| 837 @-moz-keyframes progress-bar-stripes { |
| 838 from { |
| 839 background-position: 40px 0; |
| 840 } |
| 841 to { |
| 842 background-position: 0 0; |
| 843 } |
| 844 } |
| 845 |
| 846 @-ms-keyframes progress-bar-stripes { |
| 847 from { |
| 848 background-position: 40px 0; |
| 849 } |
| 850 to { |
| 851 background-position: 0 0; |
| 852 } |
| 853 } |
| 854 |
| 855 @-o-keyframes progress-bar-stripes { |
| 856 from { |
| 857 background-position: 40px 0; |
| 858 } |
| 859 to { |
| 860 background-position: 0 0; |
| 861 } |
| 862 } |
| 863 |
| 864 @keyframes progress-bar-stripes { |
| 865 from { |
| 866 background-position: 40px 0; |
| 867 } |
| 868 to { |
| 869 background-position: 0 0; |
| 870 } |
| 871 }'''; |
| 872 |
| 873 final generated = '''.testIE-6 { |
| 874 _zoom: 5; |
| 875 } |
| 876 .clearfix { |
| 877 *zoom: 1; |
| 878 } |
| 879 audio, video { |
| 880 display: inline-block; |
| 881 *display: inline; |
| 882 *zoom: 1; |
| 883 } |
| 884 input { |
| 885 *overflow: visible; |
| 886 line-height: normal; |
| 887 } |
| 888 .uneditable-input:focus { |
| 889 border-color: rgba(82, 168, 236, 0.8); |
| 890 outline: 0; |
| 891 outline: thin dotted \\9; |
| 892 } |
| 893 input[type="radio"], input[type="checkbox"] { |
| 894 margin-top: 1px \\9; |
| 895 *margin-top: 0; |
| 896 } |
| 897 input.search-query { |
| 898 padding-right: 14px; |
| 899 padding-right: 4px \\9; |
| 900 padding-left: 14px; |
| 901 padding-left: 4px \\9; |
| 902 } |
| 903 .btn.active { |
| 904 background-color: #ccc \\9; |
| 905 } |
| 906 @-webkit-keyframes progress-bar-stripes { |
| 907 from { |
| 908 background-position: 40px 0; |
| 909 } |
| 910 to { |
| 911 background-position: 0 0; |
| 912 } |
| 913 } |
| 914 @-moz-keyframes progress-bar-stripes { |
| 915 from { |
| 916 background-position: 40px 0; |
| 917 } |
| 918 to { |
| 919 background-position: 0 0; |
| 920 } |
| 921 } |
| 922 @keyframes progress-bar-stripes { |
| 923 from { |
| 924 background-position: 40px 0; |
| 925 } |
| 926 to { |
| 927 background-position: 0 0; |
| 928 } |
| 929 } |
| 930 @-o-keyframes progress-bar-stripes { |
| 931 from { |
| 932 background-position: 40px 0; |
| 933 } |
| 934 to { |
| 935 background-position: 0 0; |
| 936 } |
| 937 } |
| 938 @keyframes progress-bar-stripes { |
| 939 from { |
| 940 background-position: 40px 0; |
| 941 } |
| 942 to { |
| 943 background-position: 0 0; |
| 944 } |
| 945 }'''; |
| 946 |
| 947 var stylesheet = parseCss(input, errors: errors, opts: simpleOptions); |
| 948 expect(stylesheet != null, true); |
| 949 expect(errors.isEmpty, true, reason: errors.toString()); |
| 950 expect(prettyPrint(stylesheet), generated); |
| 951 } |
| 952 |
| 953 void testHangs() { |
| 954 var errors = []; |
| 955 |
| 956 // Bad hexvalue had caused a hang in processTerm. |
| 957 final input = r'''#a { color: #ebebeburl(0/IE8+9+); }'''; |
| 958 var stylesheet = parseCss(input, errors: errors, opts: options); |
| 959 |
| 960 expect(stylesheet != null, true); |
| 961 expect(errors.length, 3, reason: errors.toString()); |
| 962 |
| 963 var errorMessage = errors[0]; |
| 964 expect(errorMessage.message, contains('Bad hex number')); |
| 965 expect(errorMessage.span, isNotNull); |
| 966 expect(errorMessage.span.start.line, 0); |
| 967 expect(errorMessage.span.start.column, 12); |
| 968 expect(errorMessage.span.text, '#ebebeburl'); |
| 969 |
| 970 errorMessage = errors[1]; |
| 971 expect(errorMessage.message, contains('expected }, but found +')); |
| 972 expect(errorMessage.span, isNotNull); |
| 973 expect(errorMessage.span.start.line, 0); |
| 974 expect(errorMessage.span.start.column, 30); |
| 975 expect(errorMessage.span.text, '+'); |
| 976 |
| 977 errorMessage = errors[2]; |
| 978 expect(errorMessage.message, contains('premature end of file unknown CSS')); |
| 979 expect(errorMessage.span, isNotNull); |
| 980 expect(errorMessage.span.start.line, 0); |
| 981 expect(errorMessage.span.start.column, 31); |
| 982 expect(errorMessage.span.text, ')'); |
| 983 |
| 984 // Missing closing parenthesis for keyframes. |
| 985 final input2 = r'''@-ms-keyframes progress-bar-stripes { |
| 986 from { |
| 987 background-position: 40px 0; |
| 988 } |
| 989 to { |
| 990 background-position: 0 0; |
| 991 } |
| 992 '''; |
| 993 |
| 994 stylesheet = parseCss(input2, errors: errors..clear(), opts: options); |
| 995 |
| 996 expect(stylesheet != null, true); |
| 997 |
| 998 expect(errors.length, 1, reason: errors.toString()); |
| 999 |
| 1000 errorMessage = errors[0]; |
| 1001 expect(errorMessage.message, contains('unexpected end of file')); |
| 1002 expect(errorMessage.span, isNotNull); |
| 1003 expect(errorMessage.span.start.line, 7); |
| 1004 expect(errorMessage.span.start.column, 0); |
| 1005 expect(errorMessage.span.text.trim(), ''); |
| 1006 } |
| 1007 |
| 1008 main() { |
| 1009 test('Simple Terms', testSimpleTerms); |
| 1010 test('Declarations', testDeclarations); |
| 1011 test('Identifiers', testIdentifiers); |
| 1012 test('Composites', testComposites); |
| 1013 test('Units', testUnits); |
| 1014 test('Unicode', testUnicode); |
| 1015 test('Newer CSS', testNewerCss); |
| 1016 test('Media Queries', testMediaQueries); |
| 1017 test('Font-Face', testFontFace); |
| 1018 test('CSS file', testCssFile); |
| 1019 test('Compact Emitter', testCompactEmitter); |
| 1020 test('Selector Negation', testNotSelectors); |
| 1021 test('IE stuff', testIE); |
| 1022 test('IE declaration syntax', testIEDeclaration); |
| 1023 test('Hanging bugs', testHangs); |
| 1024 } |
OLD | NEW |