postcss-merge-rules
Advanced tools
Comparing version 4.0.0-rc.2 to 4.0.0
@@ -29,9 +29,7 @@ 'use strict'; | ||
var prefixes = _vendors2.default.map(function (v) { | ||
return `-${v}-`; | ||
}); | ||
const prefixes = _vendors2.default.map(v => `-${v}-`); | ||
function intersect(a, b, not) { | ||
return a.filter(function (c) { | ||
var index = ~b.indexOf(c); | ||
return a.filter(c => { | ||
const index = ~b.indexOf(c); | ||
return not ? !index : index; | ||
@@ -41,25 +39,21 @@ }); | ||
var different = function different(a, b) { | ||
return intersect(a, b, true).concat(intersect(b, a, true)); | ||
}; | ||
var filterPrefixes = function filterPrefixes(selector) { | ||
return intersect(prefixes, selector); | ||
}; | ||
// Internet Explorer use :-ms-input-placeholder. | ||
// Microsoft Edge use ::-ms-input-placeholder. | ||
const findMsInputPlaceholder = selector => ~selector.search(/-ms-input-placeholder/i); | ||
const different = (a, b) => intersect(a, b, true).concat(intersect(b, a, true)); | ||
const filterPrefixes = selector => intersect(prefixes, selector); | ||
function sameVendor(selectorsA, selectorsB) { | ||
var same = function same(selectors) { | ||
return selectors.map(filterPrefixes).join(); | ||
}; | ||
return same(selectorsA) === same(selectorsB); | ||
let same = selectors => selectors.map(filterPrefixes).join(); | ||
let findMsVendor = selectors => selectors.find(findMsInputPlaceholder); | ||
return same(selectorsA) === same(selectorsB) && !(findMsVendor(selectorsA) && findMsVendor(selectorsB)); | ||
} | ||
var noVendor = function noVendor(selector) { | ||
return !filterPrefixes(selector).length; | ||
}; | ||
const noVendor = selector => !filterPrefixes(selector).length; | ||
function canMerge(ruleA, ruleB, browsers, compatibilityCache) { | ||
var a = ruleA.selectors; | ||
var b = ruleB.selectors; | ||
const a = ruleA.selectors; | ||
const b = ruleB.selectors; | ||
var selectors = a.concat(b); | ||
const selectors = a.concat(b); | ||
@@ -70,5 +64,4 @@ if (!(0, _ensureCompatibility2.default)(selectors, browsers, compatibilityCache)) { | ||
var parent = (0, _cssnanoUtilSameParent2.default)(ruleA, ruleB); | ||
var name = ruleA.parent.name; | ||
const parent = (0, _cssnanoUtilSameParent2.default)(ruleA, ruleB); | ||
const { name } = ruleA.parent; | ||
if (parent && name && ~name.indexOf('keyframes')) { | ||
@@ -80,29 +73,12 @@ return false; | ||
var getDecls = function getDecls(rule) { | ||
return rule.nodes && rule.nodes.map(String); | ||
}; | ||
var joinSelectors = function joinSelectors() { | ||
for (var _len = arguments.length, rules = Array(_len), _key = 0; _key < _len; _key++) { | ||
rules[_key] = arguments[_key]; | ||
} | ||
const getDecls = rule => rule.nodes && rule.nodes.map(String); | ||
const joinSelectors = (...rules) => rules.map(s => s.selector).join(); | ||
return rules.map(function (s) { | ||
return s.selector; | ||
}).join(); | ||
}; | ||
function ruleLength() { | ||
for (var _len2 = arguments.length, rules = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
rules[_key2] = arguments[_key2]; | ||
} | ||
return rules.map(function (r) { | ||
return r.nodes.length ? String(r) : ''; | ||
}).join('').length; | ||
function ruleLength(...rules) { | ||
return rules.map(r => r.nodes.length ? String(r) : '').join('').length; | ||
} | ||
function splitProp(prop) { | ||
var parts = prop.split('-'); | ||
var base = void 0, | ||
rest = void 0; | ||
const parts = prop.split('-'); | ||
let base, rest; | ||
// Treat vendor prefixed properties as if they were unprefixed; | ||
@@ -126,4 +102,4 @@ // moving them when combined with non-prefixed properties can | ||
} | ||
var a = splitProp(propA); | ||
var b = splitProp(propB); | ||
const a = splitProp(propA); | ||
const b = splitProp(propB); | ||
return a[0] === b[0] && a[1].length !== b[1].length; | ||
@@ -133,17 +109,13 @@ } | ||
function hasConflicts(declProp, notMoved) { | ||
return notMoved.some(function (prop) { | ||
return isConflictingProp(prop, declProp); | ||
}); | ||
return notMoved.some(prop => isConflictingProp(prop, declProp)); | ||
} | ||
function partialMerge(first, second) { | ||
var _this = this; | ||
var intersection = intersect(getDecls(first), getDecls(second)); | ||
let intersection = intersect(getDecls(first), getDecls(second)); | ||
if (!intersection.length) { | ||
return second; | ||
} | ||
var nextRule = second.next(); | ||
let nextRule = second.next(); | ||
if (nextRule && nextRule.type === 'rule' && canMerge(second, nextRule)) { | ||
var nextIntersection = intersect(getDecls(second), getDecls(nextRule)); | ||
let nextIntersection = intersect(getDecls(second), getDecls(nextRule)); | ||
if (nextIntersection.length > intersection.length) { | ||
@@ -153,16 +125,13 @@ first = second;second = nextRule;intersection = nextIntersection; | ||
} | ||
var recievingBlock = second.clone(); | ||
const recievingBlock = second.clone(); | ||
recievingBlock.selector = joinSelectors(first, second); | ||
recievingBlock.nodes = []; | ||
second.parent.insertBefore(second, recievingBlock); | ||
var difference = different(getDecls(first), getDecls(second)); | ||
var filterConflicts = function filterConflicts(decls, intersectn) { | ||
var willNotMove = []; | ||
return decls.reduce(function (willMove, decl) { | ||
var intersects = ~intersectn.indexOf(decl); | ||
var prop = decl.split(':')[0]; | ||
var base = prop.split('-')[0]; | ||
var canMove = difference.every(function (d) { | ||
return d.split(':')[0] !== base; | ||
}); | ||
const difference = different(getDecls(first), getDecls(second)); | ||
const filterConflicts = (decls, intersectn) => { | ||
let willNotMove = []; | ||
return decls.reduce((willMove, decl) => { | ||
let intersects = ~intersectn.indexOf(decl); | ||
let prop = decl.split(':')[0]; | ||
let base = prop.split('-')[0]; | ||
let canMove = difference.every(d => d.split(':')[0] !== base); | ||
if (intersects && canMove && !hasConflicts(prop, willNotMove)) { | ||
@@ -176,26 +145,37 @@ willMove.push(decl); | ||
}; | ||
const containsAllDeclaration = intersectionList => { | ||
return intersectionList.some(declaration => { | ||
return declaration.split(':')[0] === 'all'; | ||
}); | ||
}; | ||
intersection = filterConflicts(getDecls(first).reverse(), intersection); | ||
intersection = filterConflicts(getDecls(second), intersection); | ||
var firstClone = first.clone(); | ||
var secondClone = second.clone(); | ||
var moveDecl = function moveDecl(callback) { | ||
return function (decl) { | ||
// Rules with "all" declarations must be on top | ||
if (containsAllDeclaration(intersection)) { | ||
second.parent.insertBefore(first, recievingBlock); | ||
} else { | ||
second.parent.insertBefore(second, recievingBlock); | ||
} | ||
const firstClone = first.clone(); | ||
const secondClone = second.clone(); | ||
const moveDecl = callback => { | ||
return decl => { | ||
if (~intersection.indexOf(String(decl))) { | ||
callback.call(_this, decl); | ||
callback.call(this, decl); | ||
} | ||
}; | ||
}; | ||
firstClone.walkDecls(moveDecl(function (decl) { | ||
firstClone.walkDecls(moveDecl(decl => { | ||
decl.remove(); | ||
recievingBlock.append(decl); | ||
})); | ||
secondClone.walkDecls(moveDecl(function (decl) { | ||
return decl.remove(); | ||
})); | ||
var merged = ruleLength(firstClone, recievingBlock, secondClone); | ||
var original = ruleLength(first, second); | ||
secondClone.walkDecls(moveDecl(decl => decl.remove())); | ||
const merged = ruleLength(firstClone, recievingBlock, secondClone); | ||
const original = ruleLength(first, second); | ||
if (merged < original) { | ||
first.replaceWith(firstClone); | ||
second.replaceWith(secondClone); | ||
[firstClone, recievingBlock, secondClone].forEach(function (r) { | ||
[firstClone, recievingBlock, secondClone].forEach(r => { | ||
if (!r.nodes.length) { | ||
@@ -216,3 +196,3 @@ r.remove(); | ||
function selectorMerger(browsers, compatibilityCache) { | ||
var cache = null; | ||
let cache = null; | ||
return function (rule) { | ||
@@ -242,4 +222,4 @@ // Prime the cache with the first rule, or alternately ensure that it is | ||
if (cache.selector === rule.selector) { | ||
var cached = getDecls(cache); | ||
rule.walk(function (decl) { | ||
const cached = getDecls(cache); | ||
rule.walk(decl => { | ||
if (~cached.indexOf(String(decl))) { | ||
@@ -259,6 +239,6 @@ return decl.remove(); | ||
exports.default = _postcss2.default.plugin('postcss-merge-rules', function () { | ||
return function (css, result) { | ||
var resultOpts = result.opts || {}; | ||
var browsers = (0, _browserslist2.default)(null, { | ||
exports.default = _postcss2.default.plugin('postcss-merge-rules', () => { | ||
return (css, result) => { | ||
const resultOpts = result.opts || {}; | ||
const browsers = (0, _browserslist2.default)(null, { | ||
stats: resultOpts.stats, | ||
@@ -268,3 +248,3 @@ path: __dirname, | ||
}); | ||
var compatibilityCache = {}; | ||
const compatibilityCache = {}; | ||
css.walkRules(selectorMerger(browsers, compatibilityCache)); | ||
@@ -271,0 +251,0 @@ }; |
@@ -17,12 +17,12 @@ 'use strict'; | ||
var simpleSelectorRe = /^#?[-._a-z0-9 ]+$/i; | ||
const simpleSelectorRe = /^#?[-._a-z0-9 ]+$/i; | ||
var cssSel2 = 'css-sel2'; | ||
var cssSel3 = 'css-sel3'; | ||
var cssGencontent = 'css-gencontent'; | ||
var cssFirstLetter = 'css-first-letter'; | ||
var cssFirstLine = 'css-first-line'; | ||
var cssInOutOfRange = 'css-in-out-of-range'; | ||
const cssSel2 = 'css-sel2'; | ||
const cssSel3 = 'css-sel3'; | ||
const cssGencontent = 'css-gencontent'; | ||
const cssFirstLetter = 'css-first-letter'; | ||
const cssFirstLine = 'css-first-line'; | ||
const cssInOutOfRange = 'css-in-out-of-range'; | ||
var pseudoElements = exports.pseudoElements = { | ||
const pseudoElements = exports.pseudoElements = { | ||
':active': cssSel2, | ||
@@ -82,3 +82,3 @@ ':after': cssGencontent, | ||
} | ||
return selectors.every(function (selector) { | ||
return selectors.every(selector => { | ||
if (simpleSelectorRe.test(selector)) { | ||
@@ -90,10 +90,8 @@ return true; | ||
} | ||
var compatible = true; | ||
(0, _postcssSelectorParser2.default)(function (ast) { | ||
ast.walk(function (node) { | ||
var type = node.type, | ||
value = node.value; | ||
let compatible = true; | ||
(0, _postcssSelectorParser2.default)(ast => { | ||
ast.walk(node => { | ||
const { type, value } = node; | ||
if (type === 'pseudo') { | ||
var entry = pseudoElements[value]; | ||
const entry = pseudoElements[value]; | ||
if (entry && compatible) { | ||
@@ -100,0 +98,0 @@ compatible = (0, _caniuseApi.isSupported)(entry, browsers); |
{ | ||
"name": "postcss-merge-rules", | ||
"version": "4.0.0-rc.2", | ||
"version": "4.0.0", | ||
"description": "Merge CSS rules with PostCSS.", | ||
@@ -22,7 +22,7 @@ "main": "dist/index.js", | ||
"babel-cli": "^6.0.0", | ||
"cross-env": "^3.0.0", | ||
"postcss-discard-comments": "^4.0.0-rc.2", | ||
"postcss-simple-vars": "^3.0.0" | ||
"cross-env": "^5.0.0", | ||
"postcss-discard-comments": "^4.0.0", | ||
"postcss-simple-vars": "^4.0.0" | ||
}, | ||
"homepage": "https://github.com/ben-eb/cssnano", | ||
"homepage": "https://github.com/cssnano/cssnano", | ||
"author": { | ||
@@ -33,17 +33,17 @@ "name": "Ben Briggs", | ||
}, | ||
"repository": "ben-eb/cssnano", | ||
"repository": "cssnano/cssnano", | ||
"dependencies": { | ||
"browserslist": "^2.0.0", | ||
"browserslist": "^4.0.0", | ||
"caniuse-api": "^2.0.0", | ||
"cssnano-util-same-parent": "^4.0.0-rc.2", | ||
"cssnano-util-same-parent": "^4.0.0", | ||
"postcss": "^6.0.0", | ||
"postcss-selector-parser": "^3.0.0-rc.0", | ||
"postcss-selector-parser": "^3.0.0", | ||
"vendors": "^1.0.0" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/ben-eb/cssnano/issues" | ||
"url": "https://github.com/cssnano/cssnano/issues" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
"node": ">=6.9.0" | ||
} | ||
} |
@@ -99,3 +99,3 @@ # [postcss][postcss]-merge-rules | ||
See [CONTRIBUTORS.md](https://github.com/ben-eb/cssnano/blob/master/CONTRIBUTORS.md). | ||
See [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md). | ||
@@ -102,0 +102,0 @@ ## License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
20110
6
336
1
+ Addedbrowserslist@4.24.2(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addednode-releases@2.0.18(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedupdate-browserslist-db@1.1.1(transitive)
Updatedbrowserslist@^4.0.0