Fixes #500 - merging duplicate adjacent properties.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 10 Apr 2015 19:08:08 +0000 (20:08 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 12 Apr 2015 11:15:30 +0000 (12:15 +0100)
If values are same then there's no point keeping them as is.

History.md
lib/properties/optimizer.js
test/fixtures/big-min.css

index d319a68..334d271 100644 (file)
@@ -8,6 +8,7 @@
 * Fixed issue [#396](https://github.com/jakubpawlowicz/clean-css/issues/396) - better input source maps tracking.
 * Fixed issue [#397](https://github.com/jakubpawlowicz/clean-css/issues/397) - support for source map sources.
 * Fixed issue [#480](https://github.com/jakubpawlowicz/clean-css/issues/480) - extracting uppercase property names.
+* Fixed issue [#500](https://github.com/jakubpawlowicz/clean-css/issues/500) - merging duplicate adjacent properties.
 
 [3.1.9 / 2015-04-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.8...v3.1.9)
 ==================
index 49f5e06..ed3d33c 100644 (file)
@@ -5,6 +5,7 @@ var compactOverrides = require('./override-compactor');
 // var compactShorthands = require('./shorthand-compactor');
 var removeUnused = require('./remove-unused');
 var restoreShorthands = require('./restore-shorthands');
+var stringifyProperty = require('../stringifier/one-time').property;
 
 var shorthands = {
   'animation-delay': ['animation'],
@@ -93,6 +94,13 @@ function _optimize(properties, mergeAdjacent, aggressiveMerging) {
     return mergeAdjacent.indexOf(position) > -1;
   }
 
+  function sameValue(position) {
+    var left = properties[position - 1];
+    var right = properties[position];
+
+    return stringifyProperty(left.all, left.position) == stringifyProperty(right.all, right.position);
+  }
+
   propertyLoop:
   for (var position = 0, total = properties.length; position < total; position++) {
     var property = properties[position];
@@ -105,12 +113,17 @@ function _optimize(properties, mergeAdjacent, aggressiveMerging) {
     if (property.unused)
       continue;
 
+    if (_name == lastName && sameValue(position)) {
+      property.unused = true;
+      continue;
+    }
+
     // comment is necessary - we assume that if two properties are one after another
     // then it is intentional way of redefining property which may not be widely supported
     // e.g. a{display:inline-block;display:-moz-inline-box}
     // however if `mergeablePosition` yields true then the rule does not apply
     // (e.g merging two adjacent selectors: `a{display:block}a{display:block}`)
-    if ((aggressiveMerging && _name != lastName || mergeablePosition(position)) && _name in overrideMapping) {
+    if (_name in overrideMapping && (aggressiveMerging && _name != lastName || mergeablePosition(position))) {
       var toOverridePositions = overrideMapping[_name];
       var canOverride = compactable[_name] && compactable[_name].canOverride;
       var anyRemoved = false;
index 94f63d7..8577b36 100644 (file)
@@ -1599,8 +1599,8 @@ img.spacer{width:1px;height:1px}
 #header-liberation .header-base .nav .nav1{font-weight:400;text-transform:uppercase;font-size:11px}
 #header-liberation .header-base .nav .nav1 a{display:block}
 #header-liberation .header-base .nav .nav2{position:absolute;z-index:5000;bottom:0;left:0;width:100%}
-#core-liberation .block-basic-curled,#header-liberation .header-base .nav .nav2 li a{position:relative}
 #header-liberation .header-base .nav .nav2 li{display:block;float:left}
+#header-liberation .header-base .nav .nav2 li a{position:relative;display:block}
 #core-liberation form h2{margin-bottom:10px}
 #core-liberation form p{padding-top:10px;padding-bottom:10px}
 #core-liberation form .hidden{display:none}
@@ -1612,6 +1612,7 @@ ul.errorlist li{font-size:11px;font-weight:400;color:#e20000}
 #core-liberation .block .block-bottom span.right{float:right;display:block}
 #core-liberation .block-basic-rounded .block-top h5{text-tranform:uppercase;font-weight:400}
 #core-liberation .block-basic-rounded .block-content{border:1px solid #D8D8D8}
+#core-liberation .block-basic-curled{position:relative}
 #core-liberation .block-basic-curled .shadow-left,#core-liberation .block-basic-curled .shadow-right,#core-liberation .block-basic-curled .shadow-top-left,#core-liberation .block-basic-curled .shadow-top-right{display:block;position:absolute;z-index:0;width:35%;max-width:100%;max-height:100%}
 #core-liberation .block-basic-curled .shadow-left,#core-liberation .block-basic-curled .shadow-right{bottom:-4px}
 #core-liberation .block-basic-curled .shadow-top-left,#core-liberation .block-basic-curled .shadow-top-right{top:-4px}
@@ -1728,7 +1729,7 @@ body.iframe{padding-top:0}
 #header-liberation .header-base .nav .nav1 .on a span,#header-liberation .header-base .nav .nav1 a:hover span,#header-liberation .header-base .nav-no-js>li:hover .nav1 a span{width:9px;height:9px}
 #header-liberation .header-base .nav .nav2{display:none;height:28px}
 #header-liberation .header-base .nav .on .nav2{display:block}
-#header-liberation .header-base .nav .nav2 li a{display:block;height:26px;padding:6px 24px 0 0;font-size:12px;font-family:Arial,Verdana,sans-serif;text-transform:none}
+#header-liberation .header-base .nav .nav2 li a{height:26px;padding:6px 24px 0 0;font-size:12px;font-family:Arial,Verdana,sans-serif;text-transform:none}
 #header-liberation .header-base .nav .nav2 li.on{font-weight:700}
 #header-liberation .header-base .nav .nav2 li a span{display:block;position:absolute;top:6px;right:11px;width:1px;height:13px;left:auto}
 #header-liberation .header-base .nav .nav2 li:last-of-type a span{display:none}
@@ -2535,7 +2536,7 @@ body.access-ess #page-paywall .content .arguments .arg{float:none;margin:auto}
 .site-liberation .block-call-items .tpl-labo-podcast .emission p.subtitle{margin-bottom:10px}
 .site-liberation .block-call-items .tpl-labo-podcast .emission .visual{width:60px;height:40px}
 .site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe{clear:both}
-.site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe p.infos{font-weight:700}
+.site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe p.infos{font-weight:700;color:#222}
 .site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe p.infos span{text-transform:uppercase}
 .site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe .sb-podcasts{margin-top:10px}
 .site-liberation .block-call-items .tpl-labo-podcast .episode h4{font-weight:700;min-height:35px}
@@ -2727,7 +2728,6 @@ body.slideshow .ad-top .megaban{background:#333}
 .site-liberation .block-call-items .tpl-labo-spotlight .subtitle{color:#c6c6c6}
 .site-liberation .block-call-items .tpl-labo-spotlight .subscribe .infos,.site-liberation .block-call-items .tpl-labo-spotlight .subscribe p.toggle a{color:#fff}
 .site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe p{color:#e20000}
-.site-liberation .block-call-items .tpl-labo-podcast .emission .subscribe p.infos{color:#222}
 .site-liberation .block-call-items .tpl-search-results h4,.site-liberation .block-call-items .tpl-search-results h4 a{color:#959595}
 .site-liberation .block-call-items .tpl-search-results .object-picture .np .p1,.site-liberation .block-call-items .tpl-search-results .object-picture .np .p2{background-color:#fff;border-color:#c8c8c8}
 #core-liberation .block-comments .block-content .comment_outer,#core-liberation .block-item-read-more{border-color:#ddd}