[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * This file contains the unittests for the css optimiser in csslib.php 19 * 20 * @package core_css 21 * @category phpunit 22 * @copyright 2012 Sam Hemelryk 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->libdir . '/csslib.php'); 30 31 32 /** 33 * CSS optimiser test class. 34 * 35 * @package core_css 36 * @category phpunit 37 * @copyright 2012 Sam Hemelryk 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class core_csslib_testcase extends advanced_testcase { 41 42 /** 43 * Returns a CSS optimiser 44 * 45 * @return css_optimiser 46 */ 47 protected function get_optimiser() { 48 return new css_optimiser(); 49 } 50 51 /** 52 * Background colour tests. 53 * 54 * When testing background styles it is important to understand how the background shorthand works. 55 * background shorthand allows the following styles to be specified in a single "background" declaration: 56 * - background-color 57 * - background-image 58 * - background-repeat 59 * - background-attachment 60 * - background-position 61 * 62 * If the background shorthand is used it can contain one or more of those (preferabbly in that order). 63 * Important it does not need to contain all of them. 64 * However even if it doesn't contain values for all styles all of the styles will be affected. 65 * If a style is missed from the shorthand background style but has an existing value in the rule then the existing value 66 * is cleared. 67 * 68 * For example: 69 * .test {background: url(\'test.png\');background: bottom right;background:#123456;} 70 * will result in: 71 * .test {background:#123456;} 72 * 73 * And: 74 * .test {background-image: url(\'test.png\');background:#123456;} 75 * will result in: 76 * .test {background:#123456;} 77 */ 78 public function test_background() { 79 $optimiser = new css_optimiser(); 80 81 $cssin = '.test {background-color: #123456;}'; 82 $cssout = '.test{background-color:#123456;}'; 83 $this->assertSame($cssout, $optimiser->process($cssin)); 84 85 $cssin = '.test {background: #123456;}'; 86 $cssout = '.test{background:#123456;}'; 87 $this->assertSame($cssout, $optimiser->process($cssin)); 88 89 $cssin = '.test {background-image: url(\'test.png\');}'; 90 $cssout = '.test{background-image:url(\'test.png\');}'; 91 $this->assertSame($cssout, $optimiser->process($cssin)); 92 93 $cssin = '.test {background: #123456 url(\'test.png\') no-repeat top left;}'; 94 $cssout = '.test{background:#123456 url(\'test.png\') no-repeat top left;}'; 95 $this->assertSame($cssout, $optimiser->process($cssin)); 96 97 // Check out this for madness, background position and background-repeat have been reversed. 98 $cssin = '.test {background: #123456 url(\'test.png\') center no-repeat;}'; 99 $cssout = '.test{background:#123456 url(\'test.png\') no-repeat center;}'; 100 $this->assertSame($cssout, $optimiser->process($cssin)); 101 102 $cssin = '.test {background: url(\'test.png\') no-repeat top left;}.test{background-position: bottom right}.test {background-color:#123456;}'; 103 $cssout = '.test{background:#123456 url(\'test.png\') no-repeat bottom right;}'; 104 $this->assertSame($cssout, $optimiser->process($cssin)); 105 106 $cssin = '.test {background: url( \'test.png\' )}.test{background: bottom right}.test {background:#123456;}'; 107 $cssout = '.test{background:#123456;}'; 108 $this->assertSame($cssout, $optimiser->process($cssin)); 109 110 $cssin = '.test {background-image: url(\'test.png\');background:#123456;}'; 111 $cssout = '.test{background:#123456;}'; 112 $this->assertSame($cssout, $optimiser->process($cssin)); 113 114 $cssin = '.test {background-color: #123456;background-repeat: repeat-x; background-position: 100% 0%;}'; 115 $cssout = '.test{background-color:#123456;background-repeat:repeat-x;background-position:100% 0%;}'; 116 $this->assertSame($cssout, $optimiser->process($cssin)); 117 118 $cssin = '.tree_item.branch {background-image: url([[pix:t/expanded]]);background-position: 0 10%;background-repeat: no-repeat;} 119 .tree_item.branch.navigation_node {background-image:none;padding-left:0;}'; 120 $cssout = '.tree_item.branch{background-image:url([[pix:t/expanded]]);background-position:0 10%;background-repeat:no-repeat;} .tree_item.branch.navigation_node{background-image:none;padding-left:0;}'; 121 $this->assertSame($cssout, $optimiser->process($cssin)); 122 123 $cssin = '#nextLink{background:url(data:image/gif;base64,AAAA);}'; 124 $cssout = '#nextLink{background:url(data:image/gif;base64,AAAA);}'; 125 $this->assertSame($cssout, $optimiser->process($cssin)); 126 127 $cssin = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}'; 128 $cssout = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}'; 129 $this->assertSame($cssout, $optimiser->process($cssin)); 130 131 $cssin = '.test {background: #123456 url(data:image/gif;base64,AAAA) no-repeat top left;}'; 132 $cssout = '.test{background:#123456 url(data:image/gif;base64,AAAA) no-repeat top left;}'; 133 $this->assertSame($cssout, $optimiser->process($cssin)); 134 135 $cssin = '#test {background-image:none;background-position:right center;background-repeat:no-repeat;}'; 136 $cssout = '#test{background-image:none;background-position:right center;background-repeat:no-repeat;}'; 137 $this->assertSame($cssout, $optimiser->process($cssin)); 138 139 $cssin = '.test {background: url([[pix:theme|photos]]) no-repeat 50% 50%;background-size: 40px 40px;-webkit-background-size: 40px 40px;}'; 140 $cssout = '.test{background:url([[pix:theme|photos]]) no-repeat 50% 50%;background-size:40px 40px;-webkit-background-size:40px 40px;}'; 141 $this->assertSame($cssout, $optimiser->process($cssin)); 142 143 $cssin = '.test{background-image: -o-linear-gradient(#3c3c3c, #111);background-image: linear-gradient(#3c3c3c, #111);}'; 144 $cssout = '.test{background-image:-o-linear-gradient(#3c3c3c, #111);background-image:linear-gradient(#3c3c3c, #111);}'; 145 $this->assertSame($cssout, $optimiser->process($cssin)); 146 147 $cssin = '.test{background-image: -moz-linear-gradient(#3c3c3c, #111);background-image: -webkit-linear-gradient(#3c3c3c, #111);background-image: -o-linear-gradient(#3c3c3c, #111);background-image: linear-gradient(#3c3c3c, #111);background-image: url(/test.png);}'; 148 $cssout = '.test{background-image:url(/test.png);background-image:-moz-linear-gradient(#3c3c3c, #111);background-image:-webkit-linear-gradient(#3c3c3c, #111);background-image:-o-linear-gradient(#3c3c3c, #111);background-image:linear-gradient(#3c3c3c, #111);}'; 149 $this->assertSame($cssout, $optimiser->process($cssin)); 150 151 $cssin = '.test{background:#CCC; background-image: url(test.png);}'; 152 $cssout = '.test{background:#CCC url(test.png);}'; 153 $this->assertSame($cssout, $optimiser->process($cssin)); 154 155 $cssin = '.test{background:#CCC; background-image: linear-gradient(#3c3c3c, #111);}'; 156 $cssout = '.test{background:#CCC;background-image:linear-gradient(#3c3c3c, #111);}'; 157 $this->assertSame($cssout, $optimiser->process($cssin)); 158 159 $cssin = '.test{background:#CCC; background-image: -o-linear-gradient(#3c3c3c, #111);background-image: linear-gradient(#3c3c3c, #111);}'; 160 $cssout = '.test{background:#CCC;background-image:-o-linear-gradient(#3c3c3c, #111);background-image:linear-gradient(#3c3c3c, #111);}'; 161 $this->assertSame($cssout, $optimiser->process($cssin)); 162 163 $cssin = '#newmessageoverlay{font-weight: normal; border: 1px solid #222; background: #444; color: #ddd; text-shadow: 0 -1px 0px #000; background-image: -moz-linear-gradient(top, #333 0%, #333 5%, #444 15%, #444 60%, #222 100%); background-image: -webkit-gradient(linear, center top, center bottom, color-stop(0, #333), color-stop(5%, #333), color-stop(15%, #444), color-stop(60%, #444), color-stop(1, #222)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr=\'#333333\', EndColorStr=\'#222222\')"; padding:20px; padding-left: 0px; padding-right: 10px; position: inherit; z-index: 9999; width: 90%; margin-left: auto; margin-right: auto; height: 100%;}'; 164 $cssout = '#newmessageoverlay{font-weight:normal;border:1px solid #222;background:#444;color:#DDD;text-shadow:0 -1px 0px #000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=\'#333333\', EndColorStr=\'#222222\')";padding:20px 10px 20px 0;position:inherit;z-index:9999;width:90%;margin-left:auto;margin-right:auto;height:100%;background-image:-moz-linear-gradient(top, #333 0%, #333 5%, #444 15%, #444 60%, #222 100%);background-image:-webkit-gradient(linear, center top, center bottom, color-stop(0, #333), color-stop(5%, #333), color-stop(15%, #444), color-stop(60%, #444), color-stop(1, #222));}'; 165 $this->assertSame($cssout, $optimiser->process($cssin)); 166 167 $cssin = '.userenrolment {background-color:inherit !important;background: inherit !important;}'; 168 $cssout = '.userenrolment{background:inherit !important;}'; 169 $this->assertSame($cssout, $optimiser->process($cssin)); 170 171 $cssin = '.userenrolment {background-image:url(test.png) !important;background: inherit !important;}'; 172 $cssout = '.userenrolment{background:inherit !important;}'; 173 $this->assertSame($cssout, $optimiser->process($cssin)); 174 175 $cssin = '.userenrolment {background: inherit !important;background-image:url(test.png) !important;}'; 176 $cssout = '.userenrolment{background:inherit url(test.png) !important;}'; 177 $this->assertSame($cssout, $optimiser->process($cssin)); 178 179 $cssin = '.userenrolment {background: inherit !important;background-image:url(test.png);}'; 180 $cssout = '.userenrolment{background:inherit !important;}'; 181 $this->assertSame($cssout, $optimiser->process($cssin)); 182 183 $css = '#filesskin .yui3-widget-hd{background:#CCC;background:-webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC));background:-moz-linear-gradient(top, #FFFFFF, #CCCCCC);}'; 184 $this->assertSame($css, $optimiser->process($css)); 185 186 $css = '.userenrolment{background:-moz-linear-gradient(top, #FFFFFF, #CCCCCC) !important;}'; 187 $this->assertSame($css, $optimiser->process($css)); 188 189 $css = '.userenrolment{background:#CCC !important;background:-webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC)) !important;background:-moz-linear-gradient(top, #FFFFFF, #CCCCCC) !important;}'; 190 $this->assertSame($css, $optimiser->process($css)); 191 192 $cssin = '.userenrolment{background:-moz-linear-gradient(top, #FFFFFF, #CCCCCC) !important;}.userenrolment {background: #CCCCCC!important;background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC))!important;}'; 193 $cssout = '.userenrolment{background:#CCC !important;background:-moz-linear-gradient(top, #FFFFFF, #CCCCCC) !important;background:-webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC)) !important;}'; 194 $this->assertSame($cssout, $optimiser->process($cssin)); 195 } 196 197 /** 198 * Border tests. 199 */ 200 public function test_borders() { 201 $optimiser = new css_optimiser(); 202 203 $cssin = '.test {border: 1px solid #654321} .test {border-bottom-color: #123456}'; 204 $cssout = '.test{border:1px solid;border-color:#654321 #654321 #123456;}'; 205 $this->assertSame($cssout, $optimiser->process($cssin)); 206 207 $cssin = '.one {border:1px solid red;}'; 208 $cssout = '.one{border:1px solid #F00;}'; 209 $this->assertSame($cssout, $optimiser->process($cssin)); 210 211 $cssin = '.one {border:1px solid;} .one {border:2px dotted #DDD;}'; 212 $cssout = '.one{border:2px dotted #DDD;}'; 213 $this->assertSame($cssout, $optimiser->process($cssin)); 214 215 $cssin = '.one {border:2px dotted #DDD;}.one {border:1px solid;} '; 216 $cssout = '.one{border:1px solid #DDD;}'; 217 $this->assertSame($cssout, $optimiser->process($cssin)); 218 219 $cssin = '.one, .two {border:1px solid red;}'; 220 $cssout = ".one, .two{border:1px solid #F00;}"; 221 $this->assertSame($cssout, $optimiser->process($cssin)); 222 223 $cssin = '.one, .two {border:0px;}'; 224 $cssout = ".one, .two{border-width:0;}"; 225 $this->assertSame($cssout, $optimiser->process($cssin)); 226 227 $cssin = '.one, .two {border: thin;}'; 228 $cssout = ".one, .two{border-width:thin;}"; 229 $this->assertSame($cssout, $optimiser->process($cssin)); 230 231 $cssin = '.one, .two {border: thin solid black;}'; 232 $cssout = ".one, .two{border:thin solid #000;}"; 233 $this->assertSame($cssout, $optimiser->process($cssin)); 234 235 $cssin = '.one, .two {border-top: 5px solid white;}'; 236 $cssout = ".one, .two{border-top:5px solid #FFF;}"; 237 $this->assertSame($cssout, $optimiser->process($cssin)); 238 239 $cssin = '.one {border:1px solid red;} .two {border:1px solid red;}'; 240 $cssout = ".one, .two{border:1px solid #F00;}"; 241 $this->assertSame($cssout, $optimiser->process($cssin)); 242 243 $cssin = '.one {border:1px solid red;width:20px;} .two {border:1px solid red;height:20px;}'; 244 $cssout = ".one{border:1px solid #F00;width:20px;} .two{border:1px solid #F00;height:20px;}"; 245 $this->assertSame($cssout, $optimiser->process($cssin)); 246 247 $cssin = '.test {border: 1px solid #123456;} .test {border-color: #654321}'; 248 $cssout = '.test{border:1px solid #654321;}'; 249 $this->assertSame($cssout, $optimiser->process($cssin)); 250 251 $cssin = '.test {border-width: 1px; border-style: solid; border-color: #123456;}'; 252 $cssout = '.test{border:1px solid #123456;}'; 253 $this->assertSame($cssout, $optimiser->process($cssin)); 254 255 $cssin = '.test {border:1px solid #123456;border-top:2px dotted #654321;}'; 256 $cssout = '.test{border:1px solid #123456;border-top:2px dotted #654321;}'; 257 $this->assertSame($cssout, $optimiser->process($cssin)); 258 259 $cssin = '.test {border:1px solid #123456;border-left:2px dotted #654321;}'; 260 $cssout = '.test{border:1px solid #123456;border-left:2px dotted #654321;}'; 261 $this->assertSame($cssout, $optimiser->process($cssin)); 262 263 $cssin = '.test {border-left:2px dotted #654321;border:1px solid #123456;}'; 264 $cssout = '.test{border:1px solid #123456;}'; 265 $this->assertSame($cssout, $optimiser->process($cssin)); 266 267 $cssin = '.test {border:1px solid;border-top-color:#123456;}'; 268 $cssout = '.test{border:1px solid;border-top-color:#123456;}'; 269 $this->assertSame($cssout, $optimiser->process($cssin)); 270 271 $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;}'; 272 $cssout = '.test{border:1px solid;border-top-color:#111;border-bottom-color:#222;border-left-color:#333;}'; 273 $this->assertSame($cssout, $optimiser->process($cssin)); 274 275 $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;border-right-color:#444;}'; 276 $cssout = '.test{border:1px solid;border-color:#111 #444 #222 #333;}'; 277 $this->assertSame($cssout, $optimiser->process($cssin)); 278 279 $cssin = '.generaltable .cell {border-color:#EEE;} .generaltable .cell {border-width: 1px;border-style: solid;}'; 280 $cssout = '.generaltable .cell{border:1px solid #EEE;}'; 281 $this->assertSame($cssout, $optimiser->process($cssin)); 282 283 $cssin = '#page-admin-roles-override .rolecap {border:none;border-bottom:1px solid #CECECE;}'; 284 $cssout = '#page-admin-roles-override .rolecap{border-top:0;border-right:0;border-bottom:1px solid #CECECE;border-left:0;}'; 285 $this->assertSame($cssout, $optimiser->process($cssin)); 286 } 287 288 /** 289 * Test colour styles. 290 */ 291 public function test_colors() { 292 $optimiser = new css_optimiser(); 293 294 $css = '.css{}'; 295 $this->assertSame($css, $optimiser->process($css)); 296 297 $css = '.css{color:#123456;}'; 298 $this->assertSame($css, $optimiser->process($css)); 299 300 $css = '#some{color:#123456;}'; 301 $this->assertSame($css, $optimiser->process($css)); 302 303 $css = 'div{color:#123456;}'; 304 $this->assertSame($css, $optimiser->process($css)); 305 306 $css = 'div.css{color:#123456;}'; 307 $this->assertSame($css, $optimiser->process($css)); 308 309 $css = 'div#some{color:#123456;}'; 310 $this->assertSame($css, $optimiser->process($css)); 311 312 $css = 'div[type=blah]{color:#123456;}'; 313 $this->assertSame($css, $optimiser->process($css)); 314 315 $css = 'div.css[type=blah]{color:#123456;}'; 316 $this->assertSame($css, $optimiser->process($css)); 317 318 $css = 'div#some[type=blah]{color:#123456;}'; 319 $this->assertSame($css, $optimiser->process($css)); 320 321 $css = '#some.css[type=blah]{color:#123456;}'; 322 $this->assertSame($css, $optimiser->process($css)); 323 324 $css = '#some .css[type=blah]{color:#123456;}'; 325 $this->assertSame($css, $optimiser->process($css)); 326 327 $cssin = '.one {color:red;} .two {color:#F00;}'; 328 $cssout = ".one, .two{color:#F00;}"; 329 $this->assertSame($cssout, $optimiser->process($cssin)); 330 331 $cssin = '.one {color:#123;color:#321;}'; 332 $cssout = '.one{color:#321;}'; 333 $this->assertSame($cssout, $optimiser->process($cssin)); 334 335 $cssin = '.one {color:#123; color : #321 ;}'; 336 $cssout = '.one{color:#321;}'; 337 $this->assertSame($cssout, $optimiser->process($cssin)); 338 339 $cssin = '.one {color:#123;} .one {color:#321;}'; 340 $cssout = '.one{color:#321;}'; 341 $this->assertSame($cssout, $optimiser->process($cssin)); 342 343 $cssin = '.one {color:#123 !important;color:#321;}'; 344 $cssout = '.one{color:#123 !important;}'; 345 $this->assertSame($cssout, $optimiser->process($cssin)); 346 347 $cssin = '.one {color:#123 !important;} .one {color:#321;}'; 348 $cssout = '.one{color:#123 !important;}'; 349 $this->assertSame($cssout, $optimiser->process($cssin)); 350 351 $cssin = '.one {color:#123!important;} .one {color:#321;}'; 352 $cssout = '.one{color:#123 !important;}'; 353 $this->assertSame($cssout, $optimiser->process($cssin)); 354 355 $cssin = '.one {color:rgb(255, 128, 1)}'; 356 $cssout = '.one{color:rgb(255, 128, 1);}'; 357 $this->assertSame($cssout, $optimiser->process($cssin)); 358 359 $cssin = '.one {color:rgba(255, 128, 1, 0.5)}'; 360 $cssout = '.one{color:rgba(255, 128, 1, 0.5);}'; 361 $this->assertSame($cssout, $optimiser->process($cssin)); 362 363 $cssin = '.one {color:hsl(120, 65%, 75%)}'; 364 $cssout = '.one{color:hsl(120, 65%, 75%);}'; 365 $this->assertSame($cssout, $optimiser->process($cssin)); 366 367 $cssin = '.one {color:hsla(120,65%,75%,0.5)}'; 368 $cssout = '.one{color:hsla(120,65%,75%,0.5);}'; 369 $this->assertSame($cssout, $optimiser->process($cssin)); 370 371 // Try some invalid colours to make sure we don't mangle them. 372 $css = 'div#some{color:#1;}'; 373 $this->assertSame($css, $optimiser->process($css)); 374 375 $css = 'div#some{color:#12;}'; 376 $this->assertSame($css, $optimiser->process($css)); 377 378 $css = 'div#some{color:#1234;}'; 379 $this->assertSame($css, $optimiser->process($css)); 380 381 $css = 'div#some{color:#12345;}'; 382 $this->assertSame($css, $optimiser->process($css)); 383 } 384 385 /** 386 * Test widths. 387 */ 388 public function test_widths() { 389 $optimiser = new css_optimiser(); 390 391 $cssin = '.css {width:0}'; 392 $cssout = '.css{width:0;}'; 393 $this->assertSame($cssout, $optimiser->process($cssin)); 394 395 $cssin = '.css {width:0px}'; 396 $cssout = '.css{width:0;}'; 397 $this->assertSame($cssout, $optimiser->process($cssin)); 398 399 $cssin = '.css {width:0em}'; 400 $cssout = '.css{width:0;}'; 401 $this->assertSame($cssout, $optimiser->process($cssin)); 402 403 $cssin = '.css {width:0pt}'; 404 $cssout = '.css{width:0;}'; 405 $this->assertSame($cssout, $optimiser->process($cssin)); 406 407 $cssin = '.css {width:0mm}'; 408 $cssout = '.css{width:0;}'; 409 $this->assertSame($cssout, $optimiser->process($cssin)); 410 411 $cssin = '.css {width:100px}'; 412 $cssout = '.css{width:100px;}'; 413 $this->assertSame($cssout, $optimiser->process($cssin)); 414 } 415 416 /** 417 * Test margin styles. 418 */ 419 public function test_margins() { 420 $optimiser = new css_optimiser(); 421 422 $cssin = '.one {margin: 1px 2px 3px 4px}'; 423 $cssout = '.one{margin:1px 2px 3px 4px;}'; 424 $this->assertSame($cssout, $optimiser->process($cssin)); 425 426 $cssin = '.one {margin-top:1px; margin-left:4px; margin-right:2px; margin-bottom: 3px;}'; 427 $cssout = '.one{margin:1px 2px 3px 4px;}'; 428 $this->assertSame($cssout, $optimiser->process($cssin)); 429 430 $cssin = '.one {margin-top:1px; margin-left:4px;}'; 431 $cssout = '.one{margin-top:1px;margin-left:4px;}'; 432 $this->assertSame($cssout, $optimiser->process($cssin)); 433 434 $cssin = '.one {margin:1px; margin-left:4px;}'; 435 $cssout = '.one{margin:1px 1px 1px 4px;}'; 436 $this->assertSame($cssout, $optimiser->process($cssin)); 437 438 $cssin = '.one {margin:1px; margin-bottom:4px;}'; 439 $cssout = '.one{margin:1px 1px 4px;}'; 440 $this->assertSame($cssout, $optimiser->process($cssin)); 441 442 $cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}'; 443 $cssout = '.one, .two{margin:0;} .one.two{margin:0 7px;} .one .two{margin:0;}'; 444 $this->assertSame($cssout, $optimiser->process($cssin)); 445 446 $cssin = '.block {margin-top: 0px !important;margin-bottom: 0px !important;}'; 447 $cssout = '.block{margin-top:0 !important;margin-bottom:0 !important;}'; 448 $this->assertSame($cssout, $optimiser->process($cssin)); 449 450 $cssin = '.block {margin: 0px !important;margin-bottom: 3px;}'; 451 $cssout = '.block{margin:0 !important;}'; 452 $this->assertSame($cssout, $optimiser->process($cssin)); 453 454 $cssin = '.block {margin: 5px;margin-right: 0 !important;}'; 455 $cssout = '.block{margin:5px;margin-right:0 !important;}'; 456 $this->assertSame($cssout, $optimiser->process($cssin)); 457 } 458 459 /** 460 * Test padding styles. 461 */ 462 public function test_padding() { 463 $optimiser = new css_optimiser(); 464 465 $cssin = '.one {padding: 1px 2px 3px 4px}'; 466 $cssout = '.one{padding:1px 2px 3px 4px;}'; 467 $this->assertSame($cssout, $optimiser->process($cssin)); 468 469 $cssin = '.one {padding-top:1px; padding-left:4px; padding-right:2px; padding-bottom: 3px;}'; 470 $cssout = '.one{padding:1px 2px 3px 4px;}'; 471 $this->assertSame($cssout, $optimiser->process($cssin)); 472 473 $cssin = '.one {padding-top:1px; padding-left:4px;padding-bottom: 3px;}'; 474 $cssout = '.one{padding-top:1px;padding-left:4px;padding-bottom:3px;}'; 475 $this->assertSame($cssout, $optimiser->process($cssin)); 476 477 $cssin = '.one {padding-top:1px; padding-left:4px;}'; 478 $cssout = '.one{padding-top:1px;padding-left:4px;}'; 479 $this->assertSame($cssout, $optimiser->process($cssin)); 480 481 $cssin = '.one {padding:1px; padding-left:4px;}'; 482 $cssout = '.one{padding:1px 1px 1px 4px;}'; 483 $this->assertSame($cssout, $optimiser->process($cssin)); 484 485 $cssin = '.one {padding:1px; padding-bottom:4px;}'; 486 $cssout = '.one{padding:1px 1px 4px;}'; 487 $this->assertSame($cssout, $optimiser->process($cssin)); 488 489 $cssin = '.one {padding:0 !important;}'; 490 $cssout = '.one{padding:0 !important;}'; 491 $this->assertSame($cssout, $optimiser->process($cssin)); 492 493 $cssin = '.one {padding:0 !important;}'; 494 $cssout = '.one{padding:0 !important;}'; 495 $this->assertSame($cssout, $optimiser->process($cssin)); 496 497 $cssin = '.one, .two, .one.two, .one .two {padding:0;} .one.two {padding:0 7px;}'; 498 $cssout = '.one, .two{padding:0;} .one.two{padding:0 7px;} .one .two{padding:0;}'; 499 $this->assertSame($cssout, $optimiser->process($cssin)); 500 501 $cssin = '.block {padding-top: 0px !important;padding-bottom: 0px !important;}'; 502 $cssout = '.block{padding-top:0 !important;padding-bottom:0 !important;}'; 503 $this->assertSame($cssout, $optimiser->process($cssin)); 504 505 $cssin = '.block {padding: 0px !important;padding-bottom: 3px;}'; 506 $cssout = '.block{padding:0 !important;}'; 507 $this->assertSame($cssout, $optimiser->process($cssin)); 508 509 $cssin = '.block {padding: 5px;padding-right: 0 !important;}'; 510 $cssout = '.block{padding:5px;padding-right:0 !important;}'; 511 $this->assertSame($cssout, $optimiser->process($cssin)); 512 } 513 514 /** 515 * Test cursor optimisations 516 */ 517 public function test_cursor() { 518 $optimiser = new css_optimiser(); 519 520 // Valid cursor. 521 $cssin = '.one {cursor: pointer;}'; 522 $cssout = '.one{cursor:pointer;}'; 523 $this->assertSame($cssout, $optimiser->process($cssin)); 524 525 // Invalid cursor but tolerated. 526 $cssin = '.one {cursor: hand;}'; 527 $cssout = '.one{cursor:hand;}'; 528 $this->assertSame($cssout, $optimiser->process($cssin)); 529 530 // Valid cursor: url relative. 531 $cssin = '.one {cursor: mycursor.png;}'; 532 $cssout = '.one{cursor:mycursor.png;}'; 533 $this->assertSame($cssout, $optimiser->process($cssin)); 534 535 // Valid cursor: url absolute. 536 $cssin = '.one {cursor: http://local.host/mycursor.png;}'; 537 $cssout = '.one{cursor:http://local.host/mycursor.png;}'; 538 $this->assertSame($cssout, $optimiser->process($cssin)); 539 } 540 541 /** 542 * Test vertical align optimisations 543 */ 544 public function test_vertical_align() { 545 $optimiser = new css_optimiser(); 546 547 // Valid vertical aligns. 548 $cssin = '.one {vertical-align: baseline;}'; 549 $cssout = '.one{vertical-align:baseline;}'; 550 $this->assertSame($cssout, $optimiser->process($cssin)); 551 $cssin = '.one {vertical-align: middle;}'; 552 $cssout = '.one{vertical-align:middle;}'; 553 $this->assertSame($cssout, $optimiser->process($cssin)); 554 $cssin = '.one {vertical-align: 0.75em;}'; 555 $cssout = '.one{vertical-align:0.75em;}'; 556 $this->assertSame($cssout, $optimiser->process($cssin)); 557 $cssin = '.one {vertical-align: 50%;}'; 558 $cssout = '.one{vertical-align:50%;}'; 559 $this->assertSame($cssout, $optimiser->process($cssin)); 560 561 // Invalid but tolerated. 562 $cssin = '.one {vertical-align: center;}'; 563 $cssout = '.one{vertical-align:center;}'; 564 $this->assertSame($cssout, $optimiser->process($cssin)); 565 } 566 567 /** 568 * Test float optimisations 569 */ 570 public function test_float() { 571 $optimiser = new css_optimiser(); 572 573 // Valid vertical aligns. 574 $cssin = '.one {float: inherit;}'; 575 $cssout = '.one{float:inherit;}'; 576 $this->assertSame($cssout, $optimiser->process($cssin)); 577 $cssin = '.one {float: left;}'; 578 $cssout = '.one{float:left;}'; 579 $this->assertSame($cssout, $optimiser->process($cssin)); 580 $cssin = '.one {float: right;}'; 581 $cssout = '.one{float:right;}'; 582 $this->assertSame($cssout, $optimiser->process($cssin)); 583 $cssin = '.one {float: none;}'; 584 $cssout = '.one{float:none;}'; 585 $this->assertSame($cssout, $optimiser->process($cssin)); 586 587 // Invalid but tolerated. 588 $cssin = '.one {float: center;}'; 589 $cssout = '.one{float:center;}'; 590 $this->assertSame($cssout, $optimiser->process($cssin)); 591 } 592 593 /** 594 * Test some totally invalid CSS optimisation. 595 */ 596 public function test_invalid_css_handling() { 597 $optimiser = new css_optimiser(); 598 599 $cssin = array( 600 '.one{}', 601 '.one {:}', 602 '.one {;}', 603 '.one {;;;;;}', 604 '.one {:;}', 605 '.one {:;:;:;:::;;;}', 606 '.one {!important}', 607 '.one {:!important}', 608 '.one {:!important;}', 609 '.one {;!important}' 610 ); 611 $cssout = '.one{}'; 612 foreach ($cssin as $css) { 613 $this->assertSame($cssout, $optimiser->process($css)); 614 } 615 616 $cssin = array( 617 '.one{background-color:red;}', 618 '.one {background-color:red;} .one {background-color:}', 619 '.one {background-color:red;} .one {background-color;}', 620 '.one {background-color:red;} .one {background-color}', 621 '.one {background-color:red;} .one {background-color:;}', 622 '.one {background-color:red;} .one {:blue;}', 623 '.one {background-color:red;} .one {:#00F}', 624 ); 625 $cssout = '.one{background-color:#F00;}'; 626 foreach ($cssin as $css) { 627 $this->assertSame($cssout, $optimiser->process($css)); 628 } 629 630 $cssin = '..one {background-color:color:red}'; 631 $cssout = '..one{background-color:color:red;}'; 632 $this->assertSame($cssout, $optimiser->process($cssin)); 633 634 $cssin = '#.one {background-color:color:red}'; 635 $cssout = '#.one{background-color:color:red;}'; 636 $this->assertSame($cssout, $optimiser->process($cssin)); 637 638 $cssin = '##one {background-color:color:red}'; 639 $cssout = '##one{background-color:color:red;}'; 640 $this->assertSame($cssout, $optimiser->process($cssin)); 641 642 $cssin = '.one {background-color:color:red}'; 643 $cssout = '.one{background-color:color:red;}'; 644 $this->assertSame($cssout, $optimiser->process($cssin)); 645 646 $cssin = '.one {background-color:red;color;border-color:blue}'; 647 $cssout = '.one{background-color:#F00;border-color:#00F;}'; 648 $this->assertSame($cssout, $optimiser->process($cssin)); 649 650 $cssin = '{background-color:#123456;color:red;}{color:green;}'; 651 $cssout = "{background-color:#123456;color:#008000;}"; 652 $this->assertSame($cssout, $optimiser->process($cssin)); 653 654 $cssin = '.one {color:red;} {color:green;} .one {background-color:blue;}'; 655 $cssout = ".one{color:#F00;background-color:#00F;} {color:#008000;}"; 656 $this->assertSame($cssout, $optimiser->process($cssin)); 657 } 658 659 /** 660 * Try to break some things. 661 */ 662 public function test_break_things() { 663 $optimiser = new css_optimiser(); 664 665 // Wildcard test. 666 $cssin = '* {color: black;}'; 667 $cssout = '*{color:#000;}'; 668 $this->assertSame($cssout, $optimiser->process($cssin)); 669 670 // Wildcard test. 671 $cssin = '.one * {color: black;}'; 672 $cssout = '.one *{color:#000;}'; 673 $this->assertSame($cssout, $optimiser->process($cssin)); 674 675 // Wildcard test. 676 $cssin = '* .one * {color: black;}'; 677 $cssout = '* .one *{color:#000;}'; 678 $this->assertSame($cssout, $optimiser->process($cssin)); 679 680 // Wildcard test. 681 $cssin = '*,* {color: black;}'; 682 $cssout = '*{color:#000;}'; 683 $this->assertSame($cssout, $optimiser->process($cssin)); 684 685 // Wildcard test. 686 $cssin = '*, * .one {color: black;}'; 687 $cssout = "*, * .one{color:#000;}"; 688 $this->assertSame($cssout, $optimiser->process($cssin)); 689 690 // Wildcard test. 691 $cssin = '*, *.one {color: black;}'; 692 $cssout = "*, *.one{color:#000;}"; 693 $this->assertSame($cssout, $optimiser->process($cssin)); 694 695 // Psedo test. 696 $cssin = '.one:before {color: black;}'; 697 $cssout = '.one:before{color:#000;}'; 698 $this->assertSame($cssout, $optimiser->process($cssin)); 699 700 // Psedo test. 701 $cssin = '.one:after {color: black;}'; 702 $cssout = '.one:after{color:#000;}'; 703 $this->assertSame($cssout, $optimiser->process($cssin)); 704 705 // Psedo test. 706 $cssin = '.one:onclick {color: black;}'; 707 $cssout = '.one:onclick{color:#000;}'; 708 $this->assertSame($cssout, $optimiser->process($cssin)); 709 710 // Test complex CSS rules that don't really exist but mimic other CSS rules. 711 $cssin = '.one {master-of-destruction: explode(\' \', "What madness");}'; 712 $cssout = '.one{master-of-destruction:explode(\' \', "What madness");}'; 713 $this->assertSame($cssout, $optimiser->process($cssin)); 714 715 // Test some complex IE css... I couldn't even think of a more complext solution 716 // than the CSS they came up with. 717 $cssin = 'a { opacity: 0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50); }'; 718 $cssout = 'a{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}'; 719 $this->assertSame($cssout, $optimiser->process($cssin)); 720 } 721 722 /** 723 * A bulk processing test. 724 */ 725 public function test_bulk_processing() { 726 global $CFG; 727 $cssin = <<<CSS 728 .test .one { 729 margin:5px; 730 border:0; 731 } 732 .test .one { 733 margin: 10px; 734 color: red; 735 } 736 737 .test.one { 738 margin: 15px; 739 } 740 741 #test .one {margin: 20px;} 742 #test #one {margin: 25px;}.test #one {margin: 30px;} 743 .test .one { background-color: #123; } 744 .test.one{border:1px solid blue}.test.one{border-color:green;} 745 746 @media print { 747 #test .one {margin: 35px;} 748 } 749 750 @media print { 751 #test .one {margin: 40px;color: #123456;} 752 #test #one {margin: 45px;} 753 } 754 755 @media print,screen { 756 #test .one {color: #654321;} 757 } 758 759 #test .one, 760 #new.style {color:#000;} 761 CSS; 762 763 $cssout = <<<CSS 764 .test .one{margin:10px;border-width:0;color:#F00;background-color:#123;} 765 .test.one{margin:15px;border:1px solid #008000;} 766 #test .one{margin:20px;color:#000;} 767 #test #one{margin:25px;} 768 .test #one{margin:30px;} 769 #new.style{color:#000;} 770 771 @media print { 772 #test .one{margin:40px;color:#123456;} 773 #test #one{margin:45px;} 774 } 775 @media print,screen { 776 #test .one{color:#654321;} 777 } 778 CSS; 779 $CFG->cssoptimiserpretty = true; 780 $optimiser = new css_optimiser(); 781 $this->assertSame($optimiser->process($cssin), $cssout); 782 unset($CFG->cssoptimiserpretty); 783 } 784 785 /** 786 * Test CSS colour matching. 787 */ 788 public function test_css_is_colour() { 789 // First lets test hex colours. 790 $this->assertTrue(css_is_colour('#123456')); 791 $this->assertTrue(css_is_colour('#123')); 792 $this->assertTrue(css_is_colour('#ABCDEF')); 793 $this->assertTrue(css_is_colour('#ABC')); 794 $this->assertTrue(css_is_colour('#abcdef')); 795 $this->assertTrue(css_is_colour('#abc')); 796 $this->assertTrue(css_is_colour('#aBcDeF')); 797 $this->assertTrue(css_is_colour('#aBc')); 798 $this->assertTrue(css_is_colour('#1a2Bc3')); 799 $this->assertTrue(css_is_colour('#1Ac')); 800 801 // Note the following two colour's aren't really colours but browsers process 802 // them still. 803 $this->assertTrue(css_is_colour('#A')); 804 $this->assertTrue(css_is_colour('#12')); 805 // Having four or five characters however are not valid colours and 806 // browsers don't parse them. They need to fail so that broken CSS 807 // stays broken after optimisation. 808 $this->assertFalse(css_is_colour('#1234')); 809 $this->assertFalse(css_is_colour('#12345')); 810 811 $this->assertFalse(css_is_colour('#BCDEFG')); 812 $this->assertFalse(css_is_colour('#')); 813 $this->assertFalse(css_is_colour('#0000000')); 814 $this->assertFalse(css_is_colour('#132-245')); 815 $this->assertFalse(css_is_colour('#13 23 43')); 816 $this->assertFalse(css_is_colour('123456')); 817 818 // Next lets test real browser mapped colours. 819 $this->assertTrue(css_is_colour('black')); 820 $this->assertTrue(css_is_colour('blue')); 821 $this->assertTrue(css_is_colour('BLACK')); 822 $this->assertTrue(css_is_colour('Black')); 823 $this->assertTrue(css_is_colour('bLACK')); 824 $this->assertTrue(css_is_colour('mediumaquamarine')); 825 $this->assertTrue(css_is_colour('mediumAquamarine')); 826 $this->assertFalse(css_is_colour('monkey')); 827 $this->assertFalse(css_is_colour('')); 828 $this->assertFalse(css_is_colour('not a colour')); 829 830 // Next lets test rgb(a) colours. 831 $this->assertTrue(css_is_colour('rgb(255,255,255)')); 832 $this->assertTrue(css_is_colour('rgb(0, 0, 0)')); 833 $this->assertTrue(css_is_colour('RGB (255, 255 , 255)')); 834 $this->assertTrue(css_is_colour('rgba(0,0,0,0)')); 835 $this->assertTrue(css_is_colour('RGBA(255,255,255,1)')); 836 $this->assertTrue(css_is_colour('rgbA(255,255,255,0.5)')); 837 $this->assertFalse(css_is_colour('rgb(-255,-255,-255)')); 838 $this->assertFalse(css_is_colour('rgb(256,-256,256)')); 839 840 // Now lets test HSL colours. 841 $this->assertTrue(css_is_colour('hsl(0,0%,100%)')); 842 $this->assertTrue(css_is_colour('hsl(180, 0%, 10%)')); 843 $this->assertTrue(css_is_colour('hsl (360, 100% , 95%)')); 844 845 // Finally test the special values. 846 $this->assertTrue(css_is_colour('inherit')); 847 } 848 849 /** 850 * Test the css_is_width function. 851 */ 852 public function test_css_is_width() { 853 854 $this->assertTrue(css_is_width('0')); 855 $this->assertTrue(css_is_width('0px')); 856 $this->assertTrue(css_is_width('0em')); 857 $this->assertTrue(css_is_width('199px')); 858 $this->assertTrue(css_is_width('199em')); 859 $this->assertTrue(css_is_width('199%')); 860 $this->assertTrue(css_is_width('-1px')); 861 $this->assertTrue(css_is_width('auto')); 862 $this->assertTrue(css_is_width('inherit')); 863 864 // Valid widths but missing their unit specifier. 865 $this->assertFalse(css_is_width('0.75')); 866 $this->assertFalse(css_is_width('3')); 867 $this->assertFalse(css_is_width('-1')); 868 869 // Totally invalid widths. 870 $this->assertFalse(css_is_width('-')); 871 $this->assertFalse(css_is_width('bananas')); 872 $this->assertFalse(css_is_width('')); 873 $this->assertFalse(css_is_width('top')); 874 } 875 876 /** 877 * This function tests some of the broken crazy CSS we have in Moodle. 878 * For each of these things the value needs to be corrected if we can be 100% 879 * certain what is going wrong, Or it needs to be left as is. 880 */ 881 public function test_broken_css_found_in_moodle() { 882 $optimiser = new css_optimiser(); 883 884 // Notice how things are out of order here but that they get corrected. 885 $cssin = '.test {background:url([[pix:theme|pageheaderbgred]]) top center no-repeat}'; 886 $cssout = '.test{background:url([[pix:theme|pageheaderbgred]]) no-repeat top center;}'; 887 $this->assertSame($cssout, $optimiser->process($cssin)); 888 889 // Cursor hand isn't valid. 890 $cssin = '.test {cursor: hand;}'; 891 $cssout = '.test{cursor:hand;}'; 892 $this->assertSame($cssout, $optimiser->process($cssin)); 893 894 // Zoom property isn't valid. 895 $cssin = '.test {zoom: 1;}'; 896 $cssout = '.test{zoom:1;}'; 897 $this->assertSame($cssout, $optimiser->process($cssin)); 898 899 // Left isn't a valid position property. 900 $cssin = '.test {position: left;}'; 901 $cssout = '.test{position:left;}'; 902 $this->assertSame($cssout, $optimiser->process($cssin)); 903 904 // The dark red color isn't a valid HTML color but has a standardised 905 // translation of #8B0000. 906 $cssin = '.test {color: darkred;}'; 907 $cssout = '.test{color:#8B0000;}'; 908 $this->assertSame($cssout, $optimiser->process($cssin)); 909 910 // You can't use argb colours as border colors. 911 $cssin = '.test {border-bottom: 1px solid rgba(0,0,0,0.25);}'; 912 $cssout = '.test{border-bottom:1px solid rgba(0,0,0,0.25);}'; 913 $this->assertSame($cssout, $optimiser->process($cssin)); 914 915 // Opacity with annoying IE equivalents.... 916 $cssin = '.test {opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50);}'; 917 $cssout = '.test{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}'; 918 $this->assertSame($cssout, $optimiser->process($cssin)); 919 } 920 921 /** 922 * Test keyframe declarations. 923 */ 924 public function test_keyframe_css_animation() { 925 global $CFG; 926 $optimiser = new css_optimiser(); 927 928 $css = '.dndupload-arrow{width:56px;height:47px;position:absolute;animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;background:url(\'[[pix:theme|fp/dnd_arrow]]\') no-repeat center;margin-left:-28px;}'; 929 $this->assertSame($css, $optimiser->process($css)); 930 931 $css = '@keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}}'; 932 $this->assertSame($css, $optimiser->process($css)); 933 934 $css = "@keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}}\n"; 935 $css .= "@-moz-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}}\n"; 936 $css .= "@-webkit-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}}"; 937 $this->assertSame($css, $optimiser->process($css)); 938 939 $cssin = <<<CSS 940 .test {color:#FFF;} 941 .testtwo {color:#FFF;} 942 @media print { 943 .test {background-color:#FFF;} 944 } 945 .dndupload-arrow{width:56px;height:47px;position:absolute;animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;background:url('[[pix:theme|fp/dnd_arrow]]') no-repeat center;margin-left:-28px;} 946 @media print { 947 .test {background-color:#000;} 948 } 949 @keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}} 950 @-moz-keyframes mymove{0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}} 951 @-webkit-keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}} 952 @media print { 953 .test {background-color:#333;} 954 } 955 .test {color:#888;} 956 .testtwo {color:#888;} 957 CSS; 958 959 $cssout = <<<CSS 960 .test, 961 .testtwo{color:#888;} 962 .dndupload-arrow{width:56px;height:47px;position:absolute;animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;background:url('[[pix:theme|fp/dnd_arrow]]') no-repeat center;margin-left:-28px;} 963 964 @media print { 965 .test{background-color:#333;} 966 } 967 @keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 968 @-moz-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 969 @-webkit-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 970 CSS; 971 $CFG->cssoptimiserpretty = true; 972 $this->assertSame($cssout, $optimiser->process($cssin)); 973 unset($CFG->cssoptimiserpretty); 974 975 $cssin = <<<CSS 976 .dndupload-target {display:none;} 977 .dndsupported .dndupload-ready .dndupload-target {display:block;} 978 .dndupload-uploadinprogress {display:none;text-align:center;} 979 .dndupload-uploading .dndupload-uploadinprogress {display:block;} 980 .dndupload-arrow {background:url('[[pix:theme|fp/dnd_arrow]]') center no-repeat;width:56px;height:47px;position:absolute;margin-left: -28px;/*right:46%;left:46%;*/animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;} 981 @keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}}@-moz-keyframes mymove{0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}}@-webkit-keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}} 982 983 /* 984 * Select Dialogue (File Manager only) 985 */ 986 .filemanager.fp-select .fp-select-loading {display:none;} 987 .filemanager.fp-select.loading .fp-select-loading {display:block;} 988 .filemanager.fp-select.loading form {display:none;} 989 CSS; 990 991 $cssout = <<<CSS 992 .dndupload-target{display:none;} 993 .dndsupported .dndupload-ready .dndupload-target{display:block;} 994 .dndupload-uploadinprogress{display:none;text-align:center;} 995 .dndupload-uploading .dndupload-uploadinprogress{display:block;} 996 .dndupload-arrow{background:url('[[pix:theme|fp/dnd_arrow]]') no-repeat center;width:56px;height:47px;position:absolute;margin-left:-28px;animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;} 997 .filemanager.fp-select .fp-select-loading{display:none;} 998 .filemanager.fp-select.loading .fp-select-loading{display:block;} 999 .filemanager.fp-select.loading form{display:none;} 1000 1001 @keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 1002 @-moz-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 1003 @-webkit-keyframes mymove {0%{top:10px;}12%{top:40px;}30%{top:20px;}65%{top:35px;}100%{top:9px;}} 1004 CSS; 1005 $CFG->cssoptimiserpretty = true; 1006 $this->assertSame($cssout, $optimiser->process($cssin)); 1007 unset($CFG->cssoptimiserpretty); 1008 } 1009 1010 /** 1011 * Test media declarations. 1012 */ 1013 public function test_media_rules() { 1014 $optimiser = new css_optimiser(); 1015 1016 $cssin = "@media print {\n .test{background-color:#333;}\n}"; 1017 $cssout = "@media print { .test{background-color:#333;} }"; 1018 $this->assertSame($cssout, $optimiser->process($cssin)); 1019 1020 $cssin = "@media screen and (min-width:30px) {\n #region-main-box{left: 30px;float: left;}\n}"; 1021 $cssout = "@media screen and (min-width:30px) { #region-main-box{left:30px;float:left;} }"; 1022 $this->assertSame($cssout, $optimiser->process($cssin)); 1023 1024 $cssin = "@media all and (min-width:500px) {\n #region-main-box{left:30px;float:left;}\n}"; 1025 $cssout = "@media all and (min-width:500px) { #region-main-box{left:30px;float:left;} }"; 1026 $this->assertSame($cssout, $optimiser->process($cssin)); 1027 1028 $cssin = "@media (min-width:500px) {\n #region-main-box{left:30px;float:left;}\n}"; 1029 $cssout = "@media (min-width:500px) { #region-main-box{left:30px;float:left;} }"; 1030 $this->assertSame($cssout, $optimiser->process($cssin)); 1031 1032 $cssin = "@media screen and (color), projection and (color) {\n #region-main-box{left:30px;float:left;}\n}"; 1033 $cssout = "@media screen and (color),projection and (color) { #region-main-box{left:30px;float:left;} }"; 1034 $this->assertSame($cssout, $optimiser->process($cssin)); 1035 1036 $cssin = "@media print {\n .test{background-color:#000;}\n}@media print {\n .test{background-color:#FFF;}\n}"; 1037 $cssout = "@media print { .test{background-color:#FFF;} }"; 1038 $this->assertSame($cssout, $optimiser->process($cssin)); 1039 1040 $cssin = "@media screen and (min-width:30px) {\n #region-main-box{background-color:#000;}\n}\n@media screen and (min-width:30px) {\n #region-main-box{background-color:#FFF;}\n}"; 1041 $cssout = "@media screen and (min-width:30px) { #region-main-box{background-color:#FFF;} }"; 1042 $this->assertSame($cssout, $optimiser->process($cssin)); 1043 1044 $cssin = "@media screen and (min-width:30px) {\n #region-main-box{background-color:#000;}\n}\n@media screen and (min-width:31px) {\n #region-main-box{background-color:#FFF;}\n}"; 1045 $cssout = "@media screen and (min-width:30px) { #region-main-box{background-color:#000;} }\n@media screen and (min-width:31px) { #region-main-box{background-color:#FFF;} }"; 1046 $this->assertSame($cssout, $optimiser->process($cssin)); 1047 1048 $cssin = "@media (min-width: 768px) and (max-width: 979px) {\n*{*zoom:1;}}"; 1049 $cssout = "@media (min-width: 768px) and (max-width: 979px) { *{*zoom:1;} }"; 1050 $this->assertSame($cssout, $optimiser->process($cssin)); 1051 1052 $cssin = "#test {min-width:1200px;}@media (min-width: 768px) {#test {min-width: 1024px;}}"; 1053 $cssout = "#test{min-width:1200px;} \n@media (min-width: 768px) { #test{min-width:1024px;} }"; 1054 $this->assertSame($cssout, $optimiser->process($cssin)); 1055 1056 $cssin = "@media(min-width:768px){#page-calender-view .container fluid{min-width:1024px}}.section_add_menus{text-align:right}"; 1057 $cssout = ".section_add_menus{text-align:right;} \n@media (min-width:768px) { #page-calender-view .container fluid{min-width:1024px;} }"; 1058 $this->assertSame($cssout, $optimiser->process($cssin)); 1059 1060 $cssin = "@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}"; 1061 $cssout = "@-ms-keyframes progress-bar-stripes {from{background-position:40px 0;}to{background-position:0 0;}}"; 1062 $this->assertSame($cssout, $optimiser->process($cssin)); 1063 } 1064 1065 /** 1066 * Test the ordering of CSS optimisationss 1067 */ 1068 public function test_css_optimisation_ordering() { 1069 $optimiser = $this->get_optimiser(); 1070 1071 $css = '.test{display:none;} .dialogue{display:block;} .dialogue-hidden{display:none;}'; 1072 $this->assertSame($css, $optimiser->process($css)); 1073 1074 $cssin = '.test{display:none;} .dialogue-hidden{display:none;} .dialogue{display:block;}'; 1075 $cssout = '.test, .dialogue-hidden{display:none;} .dialogue{display:block;}'; 1076 $this->assertSame($cssout, $optimiser->process($cssin)); 1077 } 1078 1079 /** 1080 * Test CSS chunking 1081 */ 1082 public function test_css_chunking() { 1083 // Test with an even number of styles. 1084 $css = 'a{}b{}c{}d{}e{}f{}'; 1085 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1086 $this->assertInternalType('array', $chunks); 1087 $this->assertCount(3, $chunks); 1088 $this->assertArrayHasKey(0, $chunks); 1089 $this->assertArrayHasKey(1, $chunks); 1090 $this->assertArrayHasKey(2, $chunks); 1091 $this->assertSame('a{}b{}', $chunks[0]); 1092 $this->assertSame('c{}d{}', $chunks[1]); 1093 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\ne{}f{}", $chunks[2]); 1094 1095 // Test with an odd number of styles. 1096 $css = 'a{}b{}c{}d{}e{}'; 1097 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1098 $this->assertInternalType('array', $chunks); 1099 $this->assertCount(3, $chunks); 1100 $this->assertArrayHasKey(0, $chunks); 1101 $this->assertArrayHasKey(1, $chunks); 1102 $this->assertArrayHasKey(2, $chunks); 1103 $this->assertSame('a{}b{}', $chunks[0]); 1104 $this->assertSame('c{}d{}', $chunks[1]); 1105 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\ne{}", $chunks[2]); 1106 1107 // Test well placed commas. 1108 $css = 'a,b{}c,d{}e,f{}'; 1109 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1110 $this->assertInternalType('array', $chunks); 1111 $this->assertCount(3, $chunks); 1112 $this->assertArrayHasKey(0, $chunks); 1113 $this->assertArrayHasKey(1, $chunks); 1114 $this->assertArrayHasKey(2, $chunks); 1115 $this->assertSame('a,b{}', $chunks[0]); 1116 $this->assertSame('c,d{}', $chunks[1]); 1117 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\ne,f{}", $chunks[2]); 1118 1119 // Test unfortunately placed commas. 1120 $css = 'a{}b,c{color:red;}d{}e{}f{}'; 1121 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1122 $this->assertInternalType('array', $chunks); 1123 $this->assertCount(4, $chunks); 1124 $this->assertArrayHasKey(0, $chunks); 1125 $this->assertArrayHasKey(1, $chunks); 1126 $this->assertArrayHasKey(2, $chunks); 1127 $this->assertArrayHasKey(3, $chunks); 1128 $this->assertSame('a{}', $chunks[0]); 1129 $this->assertSame('b,c{color:red;}', $chunks[1]); 1130 $this->assertSame('d{}e{}', $chunks[2]); 1131 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\n@import url(styles.php?type=test&chunk=3);\nf{}", $chunks[3]); 1132 1133 // Test unfortunate CSS. 1134 $css = 'a,b,c,d,e,f{color:red;}'; 1135 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2, 0); 1136 $this->assertInternalType('array', $chunks); 1137 $this->assertCount(1, $chunks); 1138 $this->assertArrayHasKey(0, $chunks); 1139 $this->assertSame('a,b,c,d,e,f{color:red;}', $chunks[0]); 1140 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 6. Those were ignored.'); 1141 1142 // Test to make sure invalid CSS isn't totally ruined. 1143 $css = 'a{},,,e{},'; 1144 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1145 // Believe it or not we want to care what comes out here as this will be parsed correctly 1146 // by a browser. 1147 $this->assertInternalType('array', $chunks); 1148 $this->assertCount(3, $chunks); 1149 $this->assertArrayHasKey(0, $chunks); 1150 $this->assertArrayHasKey(1, $chunks); 1151 $this->assertArrayHasKey(2, $chunks); 1152 $this->assertSame('a{}', $chunks[0]); 1153 $this->assertSame(',,,e{}', $chunks[1]); 1154 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\n,", $chunks[2]); 1155 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 6. Those were ignored.'); 1156 1157 // Test utter crap CSS to make sure we don't loop to our deaths. 1158 $css = 'a,b,c,d,e,f'; 1159 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1160 $this->assertInternalType('array', $chunks); 1161 $this->assertCount(1, $chunks); 1162 $this->assertArrayHasKey(0, $chunks); 1163 $this->assertSame($css, $chunks[0]); 1164 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 6. Those were ignored.'); 1165 1166 // Test another death situation to make sure we're invincible. 1167 $css = 'a,,,,,e'; 1168 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1169 $this->assertInternalType('array', $chunks); 1170 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 4. Those were ignored.'); 1171 // I don't care what the outcome is, I just want to make sure it doesn't die. 1172 1173 // Test media queries. 1174 $css = '@media (min-width: 980px) { .a,.b{} }'; 1175 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1176 $this->assertCount(1, $chunks); 1177 $this->assertSame('@media (min-width: 980px) { .a,.b{} }', $chunks[0]); 1178 1179 // Test media queries, with commas. 1180 $css = '.a{} @media (min-width: 700px), handheld and (orientation: landscape) { .b{} }'; 1181 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1182 $this->assertCount(1, $chunks); 1183 $this->assertSame($css, $chunks[0]); 1184 1185 // Test special rules. 1186 $css = 'a,b{ background-image: linear-gradient(to bottom, #ffffff, #cccccc);}d,e{}'; 1187 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1188 $this->assertCount(2, $chunks); 1189 $this->assertSame('a,b{ background-image: linear-gradient(to bottom, #ffffff, #cccccc);}', $chunks[0]); 1190 $this->assertSame("@import url(styles.php?type=test&chunk=1);\nd,e{}", $chunks[1]); 1191 1192 // Test media queries with too many selectors. 1193 $css = '@media (min-width: 980px) { a,b,c,d{} }'; 1194 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1195 $this->assertCount(1, $chunks); 1196 $this->assertSame('@media (min-width: 980px) { a,b,c,d{} }', $chunks[0]); 1197 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 34. Those were ignored.'); 1198 1199 // Complex test. 1200 $css = '@media (a) {b{}} c{} d,e{} f,g,h{} i,j{x:a,b,c} k,l{} @media(x){l,m{ y: a,b,c}} n{}'; 1201 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 3); 1202 $this->assertCount(6, $chunks); 1203 $this->assertSame('@media (a) {b{}} c{}', $chunks[0]); 1204 $this->assertSame(' d,e{}', $chunks[1]); 1205 $this->assertSame(' f,g,h{}', $chunks[2]); 1206 $this->assertSame(' i,j{x:a,b,c}', $chunks[3]); 1207 $this->assertSame(' k,l{}', $chunks[4]); 1208 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n@import url(styles.php?type=test&chunk=2);\n@import url(styles.php?type=test&chunk=3);\n@import url(styles.php?type=test&chunk=4);\n@import url(styles.php?type=test&chunk=5);\n @media(x){l,m{ y: a,b,c}} n{}", $chunks[5]); 1209 1210 // Multiple offset errors. 1211 $css = 'a,b,c{} d,e,f{}'; 1212 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1213 $this->assertCount(2, $chunks); 1214 $this->assertSame('a,b,c{}', $chunks[0]); 1215 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n d,e,f{}", $chunks[1]); 1216 $this->assertDebuggingCalled('Could not find a safe place to split at offset(s): 6, 14. Those were ignored.'); 1217 1218 // Test the split according to IE. 1219 $css = str_repeat('a{}', 4100); 1220 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test'); 1221 $this->assertCount(2, $chunks); 1222 $this->assertSame(str_repeat('a{}', 4095), $chunks[0]); 1223 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n" . str_repeat('a{}', 5), $chunks[1]); 1224 1225 // Test strip out comments. 1226 $css = ".a {/** a\nb\nc */} /** a\nb\nc */ .b{} /** .c,.d{} */ e{}"; 1227 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1228 $this->assertCount(2, $chunks); 1229 $this->assertSame('.a {} .b{}', $chunks[0]); 1230 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n e{}", $chunks[1]); 1231 1232 // Test something with unicode characters. 1233 $css = 'a,b{} nav a:hover:after { content: "↓"; } b{ color:test;}'; 1234 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1235 $this->assertCount(2, $chunks); 1236 $this->assertSame('a,b{}', $chunks[0]); 1237 $this->assertSame("@import url(styles.php?type=test&chunk=1);\n nav a:hover:after { content: \"↓\"; } b{ color:test;}", $chunks[1]); 1238 1239 // Test that if there is broken CSS with too many close brace symbols, 1240 // media rules after that point are still kept together. 1241 $mediarule = '@media (width=480) {a{}b{}}'; 1242 $css = 'c{}}' . $mediarule . 'd{}'; 1243 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1244 $this->assertCount(3, $chunks); 1245 $this->assertEquals($mediarule, $chunks[1]); 1246 1247 // Test that this still works even with too many close brace symbols 1248 // inside a media query (note: that broken media query may be split 1249 // after the break, but any following ones should not be). 1250 $brokenmediarule = '@media (width=480) {c{}}d{}}'; 1251 $css = $brokenmediarule . 'e{}' . $mediarule . 'f{}'; 1252 $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2); 1253 $this->assertCount(4, $chunks); 1254 $this->assertEquals($mediarule, $chunks[2]); 1255 } 1256 1257 /** 1258 * Test CSS3. 1259 */ 1260 public function test_css3() { 1261 $optimiser = $this->get_optimiser(); 1262 1263 $css = '.test > .test{display:inline-block;}'; 1264 $this->assertSame($css, $optimiser->process($css)); 1265 1266 $css = '*{display:inline-block;}'; 1267 $this->assertSame($css, $optimiser->process($css)); 1268 1269 $css = 'div > *{display:inline-block;}'; 1270 $this->assertSame($css, $optimiser->process($css)); 1271 1272 $css = 'div:nth-child(3){display:inline-block;}'; 1273 $this->assertSame($css, $optimiser->process($css)); 1274 1275 $css = '.test:nth-child(3){display:inline-block;}'; 1276 $this->assertSame($css, $optimiser->process($css)); 1277 1278 $css = '*:nth-child(3){display:inline-block;}'; 1279 $this->assertSame($css, $optimiser->process($css)); 1280 1281 $css = '*[id]{display:inline-block;}'; 1282 $this->assertSame($css, $optimiser->process($css)); 1283 1284 $css = '*[id=blah]{display:inline-block;}'; 1285 $this->assertSame($css, $optimiser->process($css)); 1286 1287 $css = '*[*id=blah]{display:inline-block;}'; 1288 $this->assertSame($css, $optimiser->process($css)); 1289 1290 $css = '*[*id=blah_]{display:inline-block;}'; 1291 $this->assertSame($css, $optimiser->process($css)); 1292 1293 $css = '*[id^=blah*d]{display:inline-block;}'; 1294 $this->assertSame($css, $optimiser->process($css)); 1295 1296 $css = '.test{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}'; 1297 $this->assertSame($css, $optimiser->process($css)); 1298 1299 $css = '#test{box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);}'; 1300 $this->assertSame($css, $optimiser->process($css)); 1301 } 1302 1303 /** 1304 * Test browser hacks here. 1305 */ 1306 public function test_browser_hacks() { 1307 $optimiser = $this->get_optimiser(); 1308 1309 $css = '#test{*zoom:1;}'; 1310 $this->assertSame($css, $optimiser->process($css)); 1311 1312 $css = '.test{width:75%;*width:76%;}'; 1313 $this->assertSame($css, $optimiser->process($css)); 1314 1315 $css = '#test{*zoom:1;*display:inline;}'; 1316 $this->assertSame($css, $optimiser->process($css)); 1317 1318 $css = '.test{width:75%;*width:76%;width:76%}'; 1319 $this->assertSame('.test{width:76%;*width:76%;}', $optimiser->process($css)); 1320 1321 $css = '.test{width:75%;*width:76%;*width:75%}'; 1322 $this->assertSame('.test{width:75%;*width:75%;}', $optimiser->process($css)); 1323 } 1324 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |