MDL-45535 CSS chunking breaks media rules if CSS invalid (IE)
authorsam marshall <s.marshall@open.ac.uk>
Tue, 13 May 2014 17:43:21 +0000 (18:43 +0100)
committersam marshall <s.marshall@open.ac.uk>
Wed, 14 May 2014 11:08:27 +0000 (12:08 +0100)
Invalid CSS with extra } symbols, which previously (by fluke)
worked, was broken by recent chunking improvements. This change
makes the chunking code robust against this (stupid) situation.

lib/csslib.php
lib/tests/csslib_test.php

index 06612bb..4597d8a 100644 (file)
@@ -195,6 +195,12 @@ function css_chunk_by_selector_count($css, $importurl, $maxselectors = 4095, $bu
                 }
             } else {
                 $inrule--;
+                // Handle stupid broken CSS where there are too many } brackets,
+                // as this can cause it to break (with chunking) where it would
+                // coincidentally have worked otherwise.
+                if ($inrule < 0) {
+                    $inrule = 0;
+                }
             }
 
             // We are not in a media query, and there is no pending rule, it is safe to split here.
index 8ba3a26..099df9b 100644 (file)
@@ -1229,6 +1229,23 @@ CSS;
         $this->assertCount(2, $chunks);
         $this->assertSame('a,b{}', $chunks[0]);
         $this->assertSame("@import url(styles.php?type=test&chunk=1);\n nav a:hover:after { content: \"↓\"; } b{ color:test;}", $chunks[1]);
+
+        // Test that if there is broken CSS with too many close brace symbols,
+        // media rules after that point are still kept together.
+        $mediarule = '@media (width=480) {a{}b{}}';
+        $css = 'c{}}' . $mediarule . 'd{}';
+        $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2);
+        $this->assertCount(3, $chunks);
+        $this->assertEquals($mediarule, $chunks[1]);
+
+        // Test that this still works even with too many close brace symbols
+        // inside a media query (note: that broken media query may be split
+        // after the break, but any following ones should not be).
+        $brokenmediarule = '@media (width=480) {c{}}d{}}';
+        $css = $brokenmediarule . 'e{}' . $mediarule . 'f{}';
+        $chunks = css_chunk_by_selector_count($css, 'styles.php?type=test', 2);
+        $this->assertCount(4, $chunks);
+        $this->assertEquals($mediarule, $chunks[2]);
     }
 
     /**