Fixes #645 - adds bottom to top `media` merging.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 16 Aug 2015 14:52:10 +0000 (15:52 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 16 Aug 2015 14:52:10 +0000 (15:52 +0100)
In addition to top to bottom media merging we now support the reverse
order one. It works similar way as same selector two-way merging - see
2f8f100592908225c853997051f56bb87c35c20d.

Consider this example where top to bottom is not possible but reverse is:

```css
@media (max-width:768px){.one{padding-right:0}}
.one{padding:10px}
@media (max-width:768px){.one{margin:0}}
```

History.md
lib/selectors/merge-media-queries.js
test/fixtures/bootstrap-min.css
test/selectors/merge-media-queries-test.js

index 16f2eb1..67a594d 100644 (file)
@@ -8,6 +8,7 @@
 * Fixed issue [#612](https://github.com/jakubpawlowicz/clean-css/issues/612) - adds HTTP proxy support.
 * Fixed issue [#625](https://github.com/jakubpawlowicz/clean-css/issues/625) - adds length unit optimizations.
 * Fixed issue [#644](https://github.com/jakubpawlowicz/clean-css/issues/644) - adds time unit optimizations.
+* Fixed issue [#645](https://github.com/jakubpawlowicz/clean-css/issues/645) - adds bottom to top `media` merging.
 * Fixed issue [#648](https://github.com/jakubpawlowicz/clean-css/issues/648) - adds property level at-rule support.
 
 [3.3.9 / 2015-08-09](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.8...v3.3.9)
index 89ea572..0df0d6f 100644 (file)
@@ -24,22 +24,37 @@ function mergeMediaQueries(tokens) {
 
     positionLoop:
     for (var j = positions.length - 1; j > 0; j--) {
-      var source = tokens[positions[j]];
-      var target = tokens[positions[j - 1]];
-      var movedProperties = extractProperties(source);
+      var positionOne = positions[j];
+      var tokenOne = tokens[positionOne];
+      var positionTwo = positions[j - 1];
+      var tokenTwo = tokens[positionTwo];
 
-      for (var k = positions[j] + 1; k < positions[j - 1]; k++) {
-        var traversedProperties = extractProperties(tokens[k]);
+      directionLoop:
+      for (var direction = 1; direction >= -1; direction -= 2) {
+        var topToBottom = direction == 1;
+        var from = topToBottom ? positionOne + 1 : positionTwo - 1;
+        var to = topToBottom ? positionTwo : positionOne;
+        var delta = topToBottom ? 1 : -1;
+        var source = topToBottom ? tokenOne : tokenTwo;
+        var target = topToBottom ? tokenTwo : tokenOne;
+        var movedProperties = extractProperties(source);
 
-        // moved then traversed as we move @media towards the end
-        if (!canReorder(movedProperties, traversedProperties))
-          continue positionLoop;
-      }
+        while (from != to) {
+          var traversedProperties = extractProperties(tokens[from]);
+          from += delta;
+
+          if (!canReorder(movedProperties, traversedProperties))
+            continue directionLoop;
+        }
 
-      target[2] = source[2].concat(target[2]);
-      source[2] = [];
+        target[2] = topToBottom ?
+          source[2].concat(target[2]) :
+          target[2].concat(source[2]);
+        source[2] = [];
 
-      reduced.push(target);
+        reduced.push(target);
+        continue positionLoop;
+      }
     }
   }
 
index 19cb750..1de385f 100644 (file)
@@ -387,6 +387,7 @@ dl{margin-bottom:20px}
 dd{margin-left:0}
 @media (min-width:768px){.dl-horizontal dt{float:left;width:10pc;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}
 .dl-horizontal dd{margin-left:180px}
+.container{width:750px}
 }
 abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}
 .initialism{font-size:90%;text-transform:uppercase}
@@ -410,8 +411,6 @@ pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;color:#333;word-b
 pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;border-radius:0}
 .container,.container-fluid{padding-right:15px;padding-left:15px}
 .pre-scrollable{overflow-y:scroll}
-@media (min-width:768px){.container{width:750px}
-}
 @media (min-width:992px){.container{width:970px}
 }
 @media (min-width:1200px){.container{width:1170px}
@@ -739,13 +738,13 @@ select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-contro
 .form-inline .checkbox label,.form-inline .radio label{padding-left:0}
 .form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}
 .form-inline .has-feedback .form-control-feedback{top:0}
+.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}
 }
 .form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}
 .form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}
 .form-horizontal .form-group{margin-right:-15px;margin-left:-15px}
 .form-horizontal .has-feedback .form-control-feedback{right:15px}
-@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}
-.form-horizontal .form-group-lg .control-label{padding-top:14.33px}
+@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px}
 .form-horizontal .form-group-sm .control-label{padding-top:6px}
 }
 .btn{display:inline-block;padding:6px 9pt;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px}
@@ -969,14 +968,13 @@ select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.i
 .navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}
 .navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}
 .navbar-form .has-feedback .form-control-feedback{top:0}
+.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}
 }
 .breadcrumb>li,.pagination{display:inline-block}
 .btn .badge,.btn .label{top:-1px;position:relative}
 @media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}
 .navbar-form .form-group:last-child{margin-bottom:0}
 }
-@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}
-}
 .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}
 .navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0}
 .navbar-btn{margin-top:8px;margin-bottom:8px}
@@ -1398,6 +1396,7 @@ td.visible-lg,th.visible-lg{display:table-cell!important}
 .visible-lg-block{display:block!important}
 .visible-lg-inline{display:inline!important}
 .visible-lg-inline-block{display:inline-block!important}
+.hidden-lg{display:none!important}
 }
 @media (max-width:767px){.hidden-xs{display:none!important}
 }
@@ -1405,8 +1404,6 @@ td.visible-lg,th.visible-lg{display:table-cell!important}
 }
 @media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}
 }
-@media (min-width:1200px){.hidden-lg{display:none!important}
-}
 .visible-print{display:none!important}
 @media print{.visible-print{display:block!important}
 table.visible-print{display:table}
@@ -1422,4 +1419,4 @@ td.visible-print,th.visible-print{display:table-cell!important}
 .visible-print-inline-block{display:none!important}
 @media print{.visible-print-inline-block{display:inline-block!important}
 .hidden-print{display:none!important}
-}
\ No newline at end of file
+}
index f02c6b5..6b92626 100644 (file)
@@ -37,24 +37,24 @@ vows.describe('merge media queries')
         '@media (min-width:1024px){body{width:100%}}@media screen{a{color:red}div{display:block}}'
       ],
       'same two with breaking properties in between': [
-        '@media screen{a{color:red}}.one{color:#00f}@media screen{div{display:block}}',
-        '@media screen{a{color:red}}.one{color:#00f}@media screen{div{display:block}}'
+        '@media screen{a{color:red}}.one{color:#00f;display:inline}@media screen{div{display:block}}',
+        '@media screen{a{color:red}}.one{color:#00f;display:inline}@media screen{div{display:block}}'
       ],
       'same two with breaking @media in between': [
-        '@media screen{a{color:red}}@media (min-width:1024px){.one{color:#00f}}@media screen{div{display:block}}',
-        '@media screen{a{color:red}}@media (min-width:1024px){.one{color:#00f}}@media screen{div{display:block}}'
+        '@media screen{a{color:red}}@media (min-width:1024px){.one{color:#00f;display:inline}}@media screen{div{display:block}}',
+        '@media screen{a{color:red}}@media (min-width:1024px){.one{color:#00f;display:inline}}@media screen{div{display:block}}'
       ],
       'same two with breaking nested @media in between': [
-        '@media screen{a{color:red}}@media (min-width:1024px){@media screen{.one{color:#00f}}}@media screen{div{display:block}}',
-        '@media screen{a{color:red}}@media (min-width:1024px){@media screen{.one{color:#00f}}}@media screen{div{display:block}}'
+        '@media screen{a{color:red}}@media (min-width:1024px){@media screen{.one{color:#00f;display:inline}}}@media screen{div{display:block}}',
+        '@media screen{a{color:red}}@media (min-width:1024px){@media screen{.one{color:#00f;display:inline}}}@media screen{div{display:block}}'
       ],
       'intermixed': [
         '@media screen{a{color:red}}@media (min-width:1024px){p{width:100%}}@media screen{div{display:block}}@media (min-width:1024px){body{height:100%}}',
         '@media screen{a{color:red}div{display:block}}@media (min-width:1024px){p{width:100%}body{height:100%}}'
       ],
       'same two with overriding shorthand in between': [
-        '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:13px Helvetica}}@media screen{div{display:block}}',
-        '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:13px Helvetica}}@media screen{div{display:block}}'
+        '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:13px Helvetica;display:inline}}@media screen{div{display:block}}',
+        '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:13px Helvetica;display:inline}}@media screen{div{display:block}}'
       ],
       'same two with different component property in between': [
         '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font-weight:700}}@media screen{div{display:block}}',
@@ -71,6 +71,14 @@ vows.describe('merge media queries')
       'with comments': [
         '@media screen{a{color:red}}/*! a comment */@media screen{a{display:block}}',
         '/*! a comment */@media screen{a{color:red;display:block}}'
+      ],
+      'backwards': [
+        '@media (max-width:768px){.one{padding-right:0}}.one{padding:10px}@media (max-width:768px){.one{margin:0}}',
+        '@media (max-width:768px){.one{padding-right:0;margin:0}}.one{padding:10px}'
+      ],
+      'backward of two with overriding shorthand in between': [
+        '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:13px Helvetica}}@media screen{div{display:block}}',
+        '@media screen{a{font-size:10px}div{display:block}}@media (min-width:1024px){.one{font:13px Helvetica}}'
       ]
     })
   )