Fixes #607 - adds better rule reordering.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 17 Aug 2015 06:31:53 +0000 (07:31 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 17 Aug 2015 06:31:53 +0000 (07:31 +0100)
Apparently IDs coupled with tag selectors are safe for reordering too.

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

index fff1111..61c53e6 100644 (file)
@@ -5,6 +5,7 @@
 * Adds inferring proxy settings from HTTP_PROXY environment variable.
 * Unifies wrappers for simple & advanced optimizations.
 * Fixed issue [#599](https://github.com/jakubpawlowicz/clean-css/issues/599) - support for inlined source maps.
+* Fixed issue [#607](https://github.com/jakubpawlowicz/clean-css/issues/607) - adds better rule reordering.
 * Fixed issue [#612](https://github.com/jakubpawlowicz/clean-css/issues/612) - adds HTTP proxy support.
 * Fixed issue [#618](https://github.com/jakubpawlowicz/clean-css/issues/618) - adds safer function validation.
 * Fixed issue [#625](https://github.com/jakubpawlowicz/clean-css/issues/625) - adds length unit optimizations.
index 72cafca..df62e0e 100644 (file)
@@ -11,7 +11,7 @@ function extract(token) {
   var properties = [];
 
   if (token[0] == 'selector') {
-    var inSimpleSelector = !/[\.\+#>~\s]/.test(stringifySelectors(token[1]));
+    var inSpecificSelector = !/[\.\+>~]/.test(stringifySelectors(token[1]));
     for (var i = 0, l = token[2].length; i < l; i++) {
       var property = token[2][i];
 
@@ -34,7 +34,7 @@ function extract(token) {
         token[2][i],
         name + ':' + value,
         token[1],
-        inSimpleSelector
+        inSpecificSelector
       ]);
     }
   } else if (token[0] == 'block') {
index bae1143..2f44eb7 100644 (file)
@@ -19,12 +19,12 @@ function canReorderSingle(left, right) {
   var leftValue = left[1];
   var leftNameRoot = left[2];
   var leftSelector = left[5];
-  var leftInSimpleSelector = left[6];
+  var leftInSpecificSelector = left[6];
   var rightName = right[0];
   var rightValue = right[1];
   var rightNameRoot = right[2];
   var rightSelector = right[5];
-  var rightInSimpleSelector = right[6];
+  var rightInSpecificSelector = right[6];
 
   if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
     return false;
@@ -44,7 +44,7 @@ function canReorderSingle(left, right) {
     return true;
   if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
     return true;
-  if (rightInSimpleSelector && leftInSimpleSelector && selectorsDoNotOverlap(rightSelector, leftSelector))
+  if (rightInSpecificSelector && leftInSpecificSelector && selectorsDoNotOverlap(rightSelector, leftSelector))
     return true;
 
   return false;
index 26a1341..6f6dd1e 100644 (file)
@@ -2274,6 +2274,7 @@ form .btn-rounded-degraded input[type=button],form .btn-rounded-degraded input[t
 #core-liberation .toolbox li.spacer span{display:block;width:1px;height:20px;margin-top:5px}
 #core-liberation .toolbox .txt-min,#core-liberation .toolbox .txt-plus{display:block;font-size:15px;padding-top:4px}
 #core-liberation .toolbox .txt-reset{display:block;font-family:"Times New Roman",Times,Georgia,serif;font-size:19px;padding:4px 0 0 3px}
+#page-mailfriend,#page-paywall{font-family:Verdana,sans-serif}
 .site-liberation .toolbox li a span{display:block}
 .site-liberation .toolbox li a.print span{margin-top:7px;width:1pc;height:1pc}
 .site-liberation .toolbox li a.favorite span{margin-top:5px;width:20px;height:18px}
@@ -2300,7 +2301,6 @@ form .btn-rounded-degraded input[type=button],form .btn-rounded-degraded input[t
 #core-liberation .sb-podcasts ul li a.itunes{background-position:-267px 0;width:50px}
 #core-liberation .sb-podcasts ul li a.xml{background-position:-322px 0;width:41px}
 #bar-liberation{display:block;position:fixed;top:0;left:0;z-index:10000;width:100%;height:40px;border-bottom:1px solid;font-family:Arial,Verdana,sans-serif;font-size:9pt;line-height:14px}
-#page-mailfriend,#page-paywall{font-family:Verdana,sans-serif}
 body.init-bar-is-closed #bar-liberation{height:15px}
 #bar-liberation a,#bar-liberation a p{text-decoration:none;outline:0}
 #bar-liberation .content{position:relative;margin:auto;height:40px;width:801pt}
@@ -2868,13 +2868,13 @@ body.slideshow .ad-top .megaban{background:#333}
 #bar-liberation{background-color:#fff;box-shadow:0 1px 2px 0 #E2E2E2;-webkit-box-shadow:0 1px 2px 0 #E2E2E2;-moz-box-shadow:0 1px 2px 0 #E2E2E2}
 #bar-liberation,#bar-liberation a{color:#3c3c3c}
 #bar-liberation .content .activities-stream,#bar-liberation .content .close,#bar-liberation .content .login,#bar-liberation .content .mail-box,#bar-liberation .content .open,#bar-liberation .content .other,#bar-liberation .content .personal-options{background:#fff;border-left-color:#dadada;border-right-color:#dadada;border-bottom-color:#dadada}
+#bar-liberation #personal-options-content,#bar-liberation .content .open a .arrow{border-left-color:1px solid #dadada;border-right-color:1px solid #dadada}
 #bar-liberation .content ul.list li,#bar-liberation .content ul.list li a,#core-liberation .block-activities .block-content ul li,#core-liberation .block-activities .block-content ul li a{color:#222}
 #bar-liberation .content ul.list li span,#core-liberation .block-activities .block-content ul li span{color:#878787}
-#bar-liberation .content .open a .arrow{border-left-color:1px solid #dadada;border-right-color:1px solid #dadada}
 #bar-liberation .content .login a.subscribe{background-color:#656565;color:#fff}
 #bar-liberation .content .login a.subscribe:hover{background-color:#3c3c3c}
 #bar-liberation #login-box-content{background-color:#fff;border-left-color:#dadada;border-right-color:#dadada;box-shadow:0 1px 1px 0 #E2E2E2;-webkit-box-shadow:0 1px 1px 0 #E2E2E2;-moz-box-shadow:0 1px 1px 0 #E2E2E2}
-#bar-liberation #personal-options-content{background-color:#fff;border-left-color:1px solid #dadada;border-right-color:1px solid #dadada;border-bottom-color:1px solid #dadada;box-shadow:0 1px 1px 0 #E2E2E2;-webkit-box-shadow:0 1px 1px 0 #E2E2E2;-moz-box-shadow:0 1px 1px 0 #E2E2E2}
+#bar-liberation #personal-options-content{background-color:#fff;border-bottom-color:1px solid #dadada;box-shadow:0 1px 1px 0 #E2E2E2;-webkit-box-shadow:0 1px 1px 0 #E2E2E2;-moz-box-shadow:0 1px 1px 0 #E2E2E2}
 #bar-liberation #personal-options-content ul.subscription li.subscribe,#bar-liberation #personal-options-content ul.subscription li.subscribe a,#bar-liberation #personal-options-content ul.subscription strong{color:#a40000}
 #bar-liberation #personal-options-content ul li{color:#878787}
 #bar-liberation #personal-options-content ul li a,#bar-liberation #personal-options-content ul li strong{color:#3c3c3c}
index 2768bd7..1d4d082 100644 (file)
@@ -1,6 +1,6 @@
-h1,h3{line-height:1}
+h1 img,h2 img,h3 img,h4 img,h5 img,h6 img,html{margin:0}
 .clear,hr{clear:both}
-html{margin:0;padding:0;border:0;font-size:100.01%}
+html{padding:0;border:0;font-size:100.01%}
 a,abbr,acronym,address,article,aside,blockquote,body,caption,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,iframe,img,label,legend,li,nav,object,ol,p,pre,q,section,span,table,tbody,td,tfoot,th,thead,tr,ul{margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline}
 address,blockquote,dfn,em,tfoot{font-style:italic}
 h5,h6{font-size:1em;font-weight:700}
@@ -13,17 +13,17 @@ blockquote,q{quotes:"" ""}
 a img{border:none}
 :focus{outline:0}
 h1,h2,h3,h4,h5,h6{font-weight:400;color:#111}
-h1{font-size:3em;margin-bottom:.5em}
+h1{font-size:3em;line-height:1;margin-bottom:.5em}
 h2{font-size:2em;margin-bottom:.75em}
-h3{font-size:1.5em;margin-bottom:1em}
+h3{font-size:1.5em;line-height:1;margin-bottom:1em}
 h4{font-size:1.2em;line-height:1.25;margin-bottom:1.25em}
 h5{margin-bottom:1.5em}
-h1 img,h2 img,h3 img,h4 img,h5 img,h6 img{margin:0}
 p{margin:0 0 1.5em}
 .left{float:left!important}
 p .left{margin:1.5em 1.5em 1.5em 0;padding:0}
 .right{float:right!important}
 p .right{margin:1.5em 0 1.5em 1.5em;padding:0}
+address,dl{margin:0 0 1.5em}
 a:focus,a:hover{color:#09f}
 a{color:#06c;text-decoration:underline}
 .quiet,blockquote,del{color:#666}
@@ -31,14 +31,12 @@ blockquote{margin:1.5em}
 dfn,dl dt,strong,th{font-weight:700}
 sub,sup{line-height:0}
 abbr,acronym{border-bottom:1px dotted #666}
-address{margin:0 0 1.5em}
 pre{margin:1.5em 0;white-space:pre}
 code,pre,tt{font:1em 'andale mono','lucida console',monospace;line-height:1.5}
 li ol,li ul{margin:0}
 ol,ul{margin:0 1.5em 1.5em 0;padding-left:1.5em}
 ul{list-style-type:disc}
 ol{list-style-type:decimal}
-dl{margin:0 0 1.5em}
 dd{margin-left:1.5em}
 table{border-collapse:separate;border-spacing:0;margin-bottom:1.4em;width:100%}
 thead th{background:#c3d9ff}
index 1de385f..5b91471 100644 (file)
@@ -22,6 +22,7 @@ hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizin
 pre,textarea{overflow:auto}
 code,kbd,pre,samp{font-size:1em}
 button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}
+.glyphicon,address{font-style:normal}
 button{overflow:visible}
 button,select{text-transform:none}
 button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
@@ -54,7 +55,7 @@ select{background:#fff!important}
 .btn,.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-warning.active,.btn-warning:active,.btn.active,.btn:active,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover,.form-control,.navbar-toggle,.open>.dropdown-toggle.btn-danger,.open>.dropdown-toggle.btn-default,.open>.dropdown-toggle.btn-info,.open>.dropdown-toggle.btn-primary,.open>.dropdown-toggle.btn-warning{background-image:none}
 .img-thumbnail,body{background-color:#fff}
 @font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}
-.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
+.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
 .glyphicon-asterisk:before{content:"\2a"}
 .glyphicon-plus:before{content:"\2b"}
 .glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}
@@ -379,11 +380,11 @@ a.bg-danger:hover{background-color:#e4b9b9}
 pre code,table{background-color:transparent}
 .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}
 dl,ol,ul{margin-top:0}
+blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child,ol ol,ol ul,ul ol,ul ul{margin-bottom:0}
+address,dl{margin-bottom:20px}
 ol,ul{margin-bottom:10px}
-ol ol,ol ul,ul ol,ul ul{margin-bottom:0}
 .list-inline{margin-left:-5px}
 .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}
-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}
@@ -392,21 +393,20 @@ dd{margin-left:0}
 abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}
 .initialism{font-size:90%;text-transform:uppercase}
 blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}
-blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}
 blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;color:#777}
+legend,pre{display:block;color:#333}
 blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}
 .blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}
 code,kbd{padding:2px 4px;font-size:90%}
 caption,th{text-align:left}
 .blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}
 .blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}
-address{margin-bottom:20px;font-style:normal}
 code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}
 .popover,.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}
 code{color:#c7254e;background-color:#f9f2f4;border-radius:4px}
 kbd{color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}
 kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none}
-pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}
+pre{padding:9.5px;margin:0 0 10px;font-size:13px;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}
 .container,.container-fluid{margin-right:auto;margin-left:auto}
 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}
@@ -661,7 +661,7 @@ table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;f
 }
 fieldset,legend{padding:0;border:0}
 fieldset{min-width:0;margin:0}
-legend{display:block;width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border-bottom:1px solid #e5e5e5}
+legend{width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;border-bottom:1px solid #e5e5e5}
 label{display:inline-block;max-width:100%;margin-bottom:5px}
 input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none}
 input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}
@@ -1419,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 2348452..09e7459 100644 (file)
@@ -33,6 +33,12 @@ vows.describe(extractor)
         assert.deepEqual(tokens, [['color', 'red!important', 'color', [['color'], ['red!important']], 'color:red!important', [['a']], true]]);
       }
     },
+    'one property - simple selector': {
+      'topic': extractor(buildToken('#one span{color:red}')),
+      'has no properties': function (tokens) {
+        assert.deepEqual(tokens, [['color', 'red', 'color', [['color'], ['red']], 'color:red', [['#one span']], true]]);
+      }
+    },
     'one property - complex selector': {
       'topic': extractor(buildToken('.one{color:red}')),
       'has no properties': function (tokens) {
index 6b92626..734baaa 100644 (file)
@@ -72,6 +72,10 @@ vows.describe('merge media queries')
         '@media screen{a{color:red}}/*! a comment */@media screen{a{display:block}}',
         '/*! a comment */@media screen{a{color:red;display:block}}'
       ],
+      'with IDs mixed with type selectors': [
+        '@media (max-width:768px){#id img{display:none}}#id span{display:inline-block;width:50%}@media (max-width:768px){#id span{width:100%}}',
+        '#id span{display:inline-block;width:50%}@media (max-width:768px){#id img{display:none}#id span{width:100%}}'
+      ],
       '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}'