diff options
Diffstat (limited to 'node_modules/postcss-merge-rules/dist')
| -rw-r--r-- | node_modules/postcss-merge-rules/dist/index.js | 270 | ||||
| -rw-r--r-- | node_modules/postcss-merge-rules/dist/lib/clone.js | 35 | ||||
| -rw-r--r-- | node_modules/postcss-merge-rules/dist/lib/ensureCompatibility.js | 140 |
3 files changed, 445 insertions, 0 deletions
diff --git a/node_modules/postcss-merge-rules/dist/index.js b/node_modules/postcss-merge-rules/dist/index.js new file mode 100644 index 00000000..10aaf55e --- /dev/null +++ b/node_modules/postcss-merge-rules/dist/index.js @@ -0,0 +1,270 @@ +'use strict'; + +exports.__esModule = true; + +var _browserslist = require('browserslist'); + +var _browserslist2 = _interopRequireDefault(_browserslist); + +var _postcss = require('postcss'); + +var _postcss2 = _interopRequireDefault(_postcss); + +var _vendors = require('vendors'); + +var _vendors2 = _interopRequireDefault(_vendors); + +var _clone = require('./lib/clone'); + +var _clone2 = _interopRequireDefault(_clone); + +var _ensureCompatibility = require('./lib/ensureCompatibility'); + +var _ensureCompatibility2 = _interopRequireDefault(_ensureCompatibility); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var prefixes = _vendors2.default.map(function (v) { + return '-' + v + '-'; +}); + +function intersect(a, b, not) { + return a.filter(function (c) { + var index = ~b.indexOf(c); + return not ? !index : index; + }); +} + +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); +}; + +function sameVendor(selectorsA, selectorsB) { + var same = function same(selectors) { + return selectors.map(filterPrefixes).join(); + }; + return same(selectorsA) === same(selectorsB); +} + +var noVendor = function noVendor(selector) { + return !filterPrefixes(selector).length; +}; + +function sameParent(ruleA, ruleB) { + var hasParent = ruleA.parent && ruleB.parent; + var sameType = hasParent && ruleA.parent.type === ruleB.parent.type; + // If an at rule, ensure that the parameters are the same + if (hasParent && ruleA.parent.type !== 'root' && ruleB.parent.type !== 'root') { + sameType = sameType && ruleA.parent.params === ruleB.parent.params && ruleA.parent.name === ruleB.parent.name; + } + return hasParent ? sameType : true; +} + +function canMerge(ruleA, ruleB, browsers, compatibilityCache) { + var a = ruleA.selectors; + var b = ruleB.selectors; + + var selectors = a.concat(b); + + if (!(0, _ensureCompatibility2.default)(selectors, browsers, compatibilityCache)) { + return false; + } + + var parent = sameParent(ruleA, ruleB); + var name = ruleA.parent.name; + + if (parent && name && ~name.indexOf('keyframes')) { + return false; + } + return parent && (selectors.every(noVendor) || sameVendor(a, b)); +} + +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]; + } + + 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 splitProp(prop) { + var parts = prop.split('-'); + var base = void 0, + rest = void 0; + // Treat vendor prefixed properties as if they were unprefixed; + // moving them when combined with non-prefixed properties can + // cause issues. e.g. moving -webkit-background-clip when there + // is a background shorthand definition. + if (prop[0] === '-') { + base = parts[2]; + rest = parts.slice(3); + } else { + base = parts[0]; + rest = parts.slice(1); + } + return [base, rest]; +} + +function isConflictingProp(propA, propB) { + if (propA === propB) { + return true; + } + var a = splitProp(propA); + var b = splitProp(propB); + return a[0] === b[0] && a[1].length !== b[1].length; +} + +function hasConflicts(declProp, notMoved) { + return notMoved.some(function (prop) { + return isConflictingProp(prop, declProp); + }); +} + +function partialMerge(first, second) { + var _this = this; + + var intersection = intersect(getDecls(first), getDecls(second)); + if (!intersection.length) { + return second; + } + var nextRule = second.next(); + if (nextRule && nextRule.type === 'rule' && canMerge(second, nextRule)) { + var nextIntersection = intersect(getDecls(second), getDecls(nextRule)); + if (nextIntersection.length > intersection.length) { + first = second;second = nextRule;intersection = nextIntersection; + } + } + var recievingBlock = (0, _clone2.default)(second); + 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; + }); + if (intersects && canMove && !hasConflicts(prop, willNotMove)) { + willMove.push(decl); + } else { + willNotMove.push(prop); + } + return willMove; + }, []); + }; + intersection = filterConflicts(getDecls(first).reverse(), intersection); + intersection = filterConflicts(getDecls(second), intersection); + var firstClone = (0, _clone2.default)(first); + var secondClone = (0, _clone2.default)(second); + var moveDecl = function moveDecl(callback) { + return function (decl) { + if (~intersection.indexOf(String(decl))) { + callback.call(_this, decl); + } + }; + }; + firstClone.walkDecls(moveDecl(function (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); + if (merged < original) { + first.replaceWith(firstClone); + second.replaceWith(secondClone); + [firstClone, recievingBlock, secondClone].forEach(function (r) { + if (!r.nodes.length) { + r.remove(); + } + }); + if (!secondClone.parent) { + return recievingBlock; + } + return secondClone; + } else { + recievingBlock.remove(); + return second; + } +} + +function selectorMerger(browsers, compatibilityCache) { + var cache = null; + return function (rule) { + // Prime the cache with the first rule, or alternately ensure that it is + // safe to merge both declarations before continuing + if (!cache || !canMerge(rule, cache, browsers, compatibilityCache)) { + cache = rule; + return; + } + // Ensure that we don't deduplicate the same rule; this is sometimes + // caused by a partial merge + if (cache === rule) { + cache = rule; + return; + } + // Merge when declarations are exactly equal + // e.g. h1 { color: red } h2 { color: red } + if (getDecls(rule).join(';') === getDecls(cache).join(';')) { + rule.selector = joinSelectors(cache, rule); + cache.remove(); + cache = rule; + return; + } + // Merge when both selectors are exactly equal + // e.g. a { color: blue } a { font-weight: bold } + if (cache.selector === rule.selector) { + var cached = getDecls(cache); + rule.walk(function (decl) { + if (~cached.indexOf(String(decl))) { + return decl.remove(); + } + decl.moveTo(cache); + }); + rule.remove(); + return; + } + // Partial merge: check if the rule contains a subset of the last; if + // so create a joined selector with the subset, if smaller. + cache = partialMerge(cache, rule); + }; +} + +exports.default = _postcss2.default.plugin('postcss-merge-rules', function () { + return function (css, result) { + var opts = result.opts; + + var browsers = (0, _browserslist2.default)(null, { + stats: opts && opts.stats, + path: opts && opts.from, + env: opts && opts.env + }); + var compatibilityCache = {}; + css.walkRules(selectorMerger(browsers, compatibilityCache)); + }; +}); +module.exports = exports['default'];
\ No newline at end of file diff --git a/node_modules/postcss-merge-rules/dist/lib/clone.js b/node_modules/postcss-merge-rules/dist/lib/clone.js new file mode 100644 index 00000000..31f0bdf1 --- /dev/null +++ b/node_modules/postcss-merge-rules/dist/lib/clone.js @@ -0,0 +1,35 @@ +'use strict'; + +exports.__esModule = true; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var clone = function clone(obj, parent) { + if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || obj === null) { + return obj; + } + var cloned = new obj.constructor(); + for (var i in obj) { + if (!{}.hasOwnProperty.call(obj, i)) { + continue; + } + var value = obj[i]; + if (i === 'parent' && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') { + if (parent) { + cloned[i] = parent; + } + } else if (i === 'source') { + cloned[i] = value; + } else if (value instanceof Array) { + cloned[i] = value.map(function (j) { + return clone(j, cloned); + }); + } else { + cloned[i] = clone(value, cloned); + } + } + return cloned; +}; + +exports.default = clone; +module.exports = exports['default'];
\ No newline at end of file diff --git a/node_modules/postcss-merge-rules/dist/lib/ensureCompatibility.js b/node_modules/postcss-merge-rules/dist/lib/ensureCompatibility.js new file mode 100644 index 00000000..57029e94 --- /dev/null +++ b/node_modules/postcss-merge-rules/dist/lib/ensureCompatibility.js @@ -0,0 +1,140 @@ +'use strict'; + +exports.__esModule = true; +exports.pseudoElements = undefined; +exports.default = ensureCompatibility; + +var _caniuseApi = require('caniuse-api'); + +var _postcssSelectorParser = require('postcss-selector-parser'); + +var _postcssSelectorParser2 = _interopRequireDefault(_postcssSelectorParser); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var 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'; + +var pseudoElements = exports.pseudoElements = { + ':active': cssSel2, + ':after': cssGencontent, + ':before': cssGencontent, + ':checked': cssSel3, + ':default': 'css-default-pseudo', + ':dir': 'css-dir-pseudo', + ':disabled': cssSel3, + ':empty': cssSel3, + ':enabled': cssSel3, + ':first-child': cssSel2, + ':first-letter': cssFirstLetter, + ':first-line': cssFirstLine, + ':first-of-type': cssSel3, + ':focus': cssSel2, + ':focus-within': 'css-focus-within', + ':has': 'css-has', + ':hover': cssSel2, + ':in-range': cssInOutOfRange, + ':indeterminate': 'css-indeterminate-pseudo', + ':lang': cssSel2, + ':last-child': cssSel3, + ':last-of-type': cssSel3, + ':matches': 'css-matches-pseudo', + ':not': cssSel3, + ':nth-child': cssSel3, + ':nth-last-child': cssSel3, + ':nth-last-of-type': cssSel3, + ':nth-of-type': cssSel3, + ':only-child': cssSel3, + ':only-of-type': cssSel3, + ':optional': 'css-optional-pseudo', + ':out-of-range': cssInOutOfRange, + ':placeholder-shown': 'css-placeholder-shown', + ':root': cssSel3, + ':target': cssSel3, + '::after': cssGencontent, + '::backdrop': 'dialog', + '::before': cssGencontent, + '::first-letter': cssFirstLetter, + '::first-line': cssFirstLine, + '::marker': 'css-marker-pseudo', + '::placeholder': 'css-placeholder', + '::selection': 'css-selection' +}; + +function isCssMixin(selector) { + return selector[selector.length - 1] === ':'; +} + +function ensureCompatibility(selectors, browsers, compatibilityCache) { + // Should not merge mixins + if (selectors.some(isCssMixin)) { + return false; + } + return selectors.every(function (selector) { + if (simpleSelectorRe.test(selector)) { + return true; + } + if (compatibilityCache && selector in compatibilityCache) { + return compatibilityCache[selector]; + } + var compatible = true; + (0, _postcssSelectorParser2.default)(function (ast) { + ast.walk(function (node) { + var type = node.type, + value = node.value; + + if (type === 'pseudo') { + var entry = pseudoElements[value]; + if (entry && compatible) { + compatible = (0, _caniuseApi.isSupported)(entry, browsers); + } + } + if (type === 'combinator') { + if (~value.indexOf('~')) { + compatible = (0, _caniuseApi.isSupported)(cssSel3, browsers); + } + if (~value.indexOf('>') || ~value.indexOf('+')) { + compatible = (0, _caniuseApi.isSupported)(cssSel2, browsers); + } + } + if (type === 'attribute' && node.attribute) { + // [foo] + if (!node.operator) { + compatible = (0, _caniuseApi.isSupported)(cssSel2, browsers); + } + + if (value) { + // [foo="bar"], [foo~="bar"], [foo|="bar"] + if (~['=', '~=', '|='].indexOf(node.operator)) { + compatible = (0, _caniuseApi.isSupported)(cssSel2, browsers); + } + // [foo^="bar"], [foo$="bar"], [foo*="bar"] + if (~['^=', '$=', '*='].indexOf(node.operator)) { + compatible = (0, _caniuseApi.isSupported)(cssSel3, browsers); + } + } + + // [foo="bar" i] + if (node.insensitive) { + compatible = (0, _caniuseApi.isSupported)('css-case-insensitive', browsers); + } + } + if (!compatible) { + // If this node was not compatible, + // break out early from walking the rest + return false; + } + }); + }).process(selector); + if (compatibilityCache) { + compatibilityCache[selector] = compatible; + } + return compatible; + }); +}
\ No newline at end of file |
