From: Jakub Pawlowicz Date: Tue, 10 Feb 2015 07:31:00 +0000 (+0000) Subject: Improves selector traversal in advanced merging. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=7ac74d54ebe361e098e9dcbda4cf1a75f7dbc377;p=clean-css.git Improves selector traversal in advanced merging. Selectors can be reordered if one of the following rules regarding any pair of its properties is met: * Property name root (`font` in `font-size`) is different, e.g. `margin:0` <-> `color:red` * Property name root, name, and value are the same, e.g. `color:red` <-> `color:red` `margin-top:0` <-> `margin-top:0` * Property name root is the same, names are different, and any name is not root, e.g `margin-top:0` <-> `margin-bottom:10px` --- diff --git a/lib/selectors/optimizers/advanced.js b/lib/selectors/optimizers/advanced.js index 11c4d455..4cd6fb34 100644 --- a/lib/selectors/optimizers/advanced.js +++ b/lib/selectors/optimizers/advanced.js @@ -30,9 +30,13 @@ function allProperties(token) { for (var i = token.metadata.bodiesList.length - 1; i >= 0; i--) { var property = token.metadata.bodiesList[i]; var splitAt = property.indexOf(':'); + var name = property.substring(0, splitAt); + var nameRoot = name.match(/([a-z]+)/)[0]; + properties.push([ - property.substring(0, splitAt).match(/([a-z]+)/)[0], - property.substring(splitAt + 1) + name, + property.substring(splitAt + 1), + nameRoot ]); } } else if (token.kind == 'block') { @@ -49,11 +53,19 @@ function canReorder(left, right) { for (var j = left.length - 1; j >= 0; j--) { var rightName = right[i][0]; var rightValue = right[i][1]; + var rightNameRoot = right[i][2]; var leftName = left[j][0]; var leftValue = left[j][1]; + var leftNameRoot = left[j][2]; + + if (rightNameRoot != leftNameRoot) + continue; + if (rightName == leftName && rightNameRoot == leftNameRoot && rightValue == leftValue) + continue; + if (rightName != leftName && rightNameRoot == leftNameRoot && rightName != rightNameRoot && leftName != leftNameRoot) + continue; - if (rightName == leftName && rightValue != leftValue) - return false; + return false; } } @@ -334,7 +346,9 @@ AdvancedOptimizer.prototype.mergeNonAdjacentBySelector = function (tokens) { if (tokens[k].kind == 'selector') { var traversedProperties = allProperties(tokens[k]); - if (!canReorder(movedProperties, traversedProperties)) + + // traversed then moved as we move selectors towards the start + if (!canReorder(traversedProperties, movedProperties)) continue selectorIterator; } } @@ -403,6 +417,8 @@ AdvancedOptimizer.prototype.mergeMediaQueries = function (tokens) { for (var k = positions[j] + 1; k < positions[j - 1]; k++) { var traversedProperties = allProperties(tokens[k]); + + // moved then traversed as we move @media towards the end if (!canReorder(movedProperties, traversedProperties)) continue positionLoop; } diff --git a/test/fixtures/big-min.css b/test/fixtures/big-min.css index 3ec3640c..5023e4f8 100644 --- a/test/fixtures/big-min.css +++ b/test/fixtures/big-min.css @@ -1720,7 +1720,7 @@ body.iframe{padding-top:0} #header-liberation .header-base .links{display:block;width:280px;height:110px;padding-top:10px} #header-liberation .header-base .links .lnk1,#header-liberation .header-base .links .lnk2{float:left} #header-liberation .header-base .links .lnk1{position:relative;width:123px} -#header-liberation .header-base .links .lnk2{width:136px;padding-left:21px} +#header-liberation .header-base .links .lnk2{width:136px;padding-left:21px;box-shadow:-9px 0 10px -11px #6c6c6c;-moz-box-shadow:-9px 0 10px -11px #6c6c6c;-webkit-box-shadow:-9px 0 10px -11px #6c6c6c} #header-liberation .header-base .links h2{margin-bottom:3px} #header-liberation .header-base .links ul li{margin-bottom:1px;height:13px} #header-liberation .header-base .digitalpaper{position:relative;float:right;width:196px} @@ -2638,7 +2638,6 @@ body.slideshow .ad-top .megaban{background:#333} .site-liberation .hot-topics li{background:#fff} .site-liberation .hot-topics .event{background:#b1b1b1} .site-liberation #footer-liberation .hot-topics .event a{color:#fff} -#header-liberation .header-base .links .lnk2{box-shadow:-9px 0 10px -11px #6c6c6c;-moz-box-shadow:-9px 0 10px -11px #6c6c6c;-webkit-box-shadow:-9px 0 10px -11px #6c6c6c} #header-liberation .header-base .digitalpaper a.abo,#header-liberation .header-base .digitalpaper a.dl{color:#fff} #header-liberation .header-base .digitalpaper a.abo{background-color:#f2f2f2;color:#2e2e2e} #header-liberation .header-base .digitalpaper a.une{box-shadow:0 -1px 7px 0 grey;-webkit-box-shadow:0 -1px 7px 0 grey;-moz-box-shadow:0 -1px 7px 0 grey} diff --git a/test/integration-test.js b/test/integration-test.js index 70f1dc65..e4adadd0 100644 --- a/test/integration-test.js +++ b/test/integration-test.js @@ -1806,6 +1806,10 @@ title']{display:block}", '.one{color:red;margin:0}.two{font:12px serif}.one{font-size:12px}', '.one{color:red;margin:0}.two{font:12px serif}.one{font-size:12px}' ], + 'with granular selectors from the same shorthand': [ + '.one{color:red;margin:0}.two{font-weight:700}.one{font-size:12px}', + '.one{color:red;margin:0;font-size:12px}.two{font-weight:700}' + ], 'with three intermediate, non-overriding selectors': [ '.one{color:red;margin:0}.two{color:#fff}.one{font-size:12px}.three{color:#000}.one{padding:0}', '.one{color:red;margin:0;font-size:12px;padding:0}.two{color:#fff}.three{color:#000}' diff --git a/test/media-queries-test.js b/test/media-queries-test.js index abeff2e0..4d411c20 100644 --- a/test/media-queries-test.js +++ b/test/media-queries-test.js @@ -72,6 +72,12 @@ vows.describe('media queries') assert.equal(minified.styles, '@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font:12px Helvetica}}@media screen{div{display:block}}'); } }, + 'same two with different component property in between': { + topic: new CleanCSS().minify('@media screen{a{font-size:10px}}@media (min-width:1024px){.one{font-weight:700}}@media screen{div{display:block}}'), + 'get merged': function(minified) { + assert.equal(minified.styles, '@media (min-width:1024px){.one{font-weight:700}}@media screen{a{font-size:10px}div{display:block}}'); + } + }, 'same two with same values as moved in between': { topic: new CleanCSS().minify('@media screen{a{color:red}}@media (min-width:1024px){.one{color:red}}@media screen{div{display:block}}'), 'get merged': function(minified) {