| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 | 
							- 'use strict';
 
- var csstree     = require('css-tree'),
 
-     List        = csstree.List,
 
-     stable      = require('stable'),
 
-     specificity = require('csso/lib/restructure/prepare/specificity');
 
- /**
 
-  * Flatten a CSS AST to a selectors list.
 
-  *
 
-  * @param {Object} cssAst css-tree AST to flatten
 
-  * @return {Array} selectors
 
-  */
 
- function flattenToSelectors(cssAst) {
 
-     var selectors = [];
 
-     csstree.walk(cssAst, {visit: 'Rule', enter: function(node) {
 
-         if (node.type !== 'Rule') {
 
-             return;
 
-         }
 
-         var atrule = this.atrule;
 
-         var rule = node;
 
-         node.prelude.children.each(function(selectorNode, selectorItem) {
 
-             var selector = {
 
-                 item: selectorItem,
 
-                 atrule: atrule,
 
-                 rule: rule,
 
-                 pseudos: []
 
-             };
 
-             selectorNode.children.each(function(selectorChildNode, selectorChildItem, selectorChildList) {
 
-                 if (selectorChildNode.type === 'PseudoClassSelector' ||
 
-                     selectorChildNode.type === 'PseudoElementSelector') {
 
-                     selector.pseudos.push({
 
-                         item: selectorChildItem,
 
-                         list: selectorChildList
 
-                     });
 
-                 }
 
-             });
 
-             selectors.push(selector);
 
-         });
 
-     }});
 
-     return selectors;
 
- }
 
- /**
 
-  * Filter selectors by Media Query.
 
-  *
 
-  * @param {Array} selectors to filter
 
-  * @param {Array} useMqs Array with strings of media queries that should pass (<name> <expression>)
 
-  * @return {Array} Filtered selectors that match the passed media queries
 
-  */
 
- function filterByMqs(selectors, useMqs) {
 
-     return selectors.filter(function(selector) {
 
-         if (selector.atrule === null) {
 
-             return ~useMqs.indexOf('');
 
-         }
 
-         var mqName = selector.atrule.name;
 
-         var mqStr = mqName;
 
-         if (selector.atrule.expression &&
 
-             selector.atrule.expression.children.first().type === 'MediaQueryList') {
 
-             var mqExpr = csstree.generate(selector.atrule.expression);
 
-             mqStr = [mqName, mqExpr].join(' ');
 
-         }
 
-         return ~useMqs.indexOf(mqStr);
 
-     });
 
- }
 
- /**
 
-  * Filter selectors by the pseudo-elements and/or -classes they contain.
 
-  *
 
-  * @param {Array} selectors to filter
 
-  * @param {Array} usePseudos Array with strings of single or sequence of pseudo-elements and/or -classes that should pass
 
-  * @return {Array} Filtered selectors that match the passed pseudo-elements and/or -classes
 
-  */
 
- function filterByPseudos(selectors, usePseudos) {
 
-     return selectors.filter(function(selector) {
 
-         var pseudoSelectorsStr = csstree.generate({
 
-             type: 'Selector',
 
-             children: new List().fromArray(selector.pseudos.map(function(pseudo) {
 
-                 return pseudo.item.data;
 
-             }))
 
-         });
 
-         return ~usePseudos.indexOf(pseudoSelectorsStr);
 
-     });
 
- }
 
- /**
 
-  * Remove pseudo-elements and/or -classes from the selectors for proper matching.
 
-  *
 
-  * @param {Array} selectors to clean
 
-  * @return {Array} Selectors without pseudo-elements and/or -classes
 
-  */
 
- function cleanPseudos(selectors) {
 
-     selectors.forEach(function(selector) {
 
-         selector.pseudos.forEach(function(pseudo) {
 
-             pseudo.list.remove(pseudo.item);
 
-         });
 
-     });
 
- }
 
- /**
 
-  * Compares two selector specificities.
 
-  * extracted from https://github.com/keeganstreet/specificity/blob/master/specificity.js#L211
 
-  *
 
-  * @param {Array} aSpecificity Specificity of selector A
 
-  * @param {Array} bSpecificity Specificity of selector B
 
-  * @return {Number} Score of selector specificity A compared to selector specificity B
 
-  */
 
- function compareSpecificity(aSpecificity, bSpecificity) {
 
-     for (var i = 0; i < 4; i += 1) {
 
-         if (aSpecificity[i] < bSpecificity[i]) {
 
-             return -1;
 
-         } else if (aSpecificity[i] > bSpecificity[i]) {
 
-             return 1;
 
-         }
 
-     }
 
-     return 0;
 
- }
 
- /**
 
-  * Compare two simple selectors.
 
-  *
 
-  * @param {Object} aSimpleSelectorNode Simple selector A
 
-  * @param {Object} bSimpleSelectorNode Simple selector B
 
-  * @return {Number} Score of selector A compared to selector B
 
-  */
 
- function compareSimpleSelectorNode(aSimpleSelectorNode, bSimpleSelectorNode) {
 
-     var aSpecificity = specificity(aSimpleSelectorNode),
 
-         bSpecificity = specificity(bSimpleSelectorNode);
 
-     return compareSpecificity(aSpecificity, bSpecificity);
 
- }
 
- function _bySelectorSpecificity(selectorA, selectorB) {
 
-     return compareSimpleSelectorNode(selectorA.item.data, selectorB.item.data);
 
- }
 
- /**
 
-  * Sort selectors stably by their specificity.
 
-  *
 
-  * @param {Array} selectors to be sorted
 
-  * @return {Array} Stable sorted selectors
 
-  */
 
- function sortSelectors(selectors) {
 
-     return stable(selectors, _bySelectorSpecificity);
 
- }
 
- /**
 
-  * Convert a css-tree AST style declaration to CSSStyleDeclaration property.
 
-  *
 
-  * @param {Object} declaration css-tree style declaration
 
-  * @return {Object} CSSStyleDeclaration property
 
-  */
 
- function csstreeToStyleDeclaration(declaration) {
 
-     var propertyName = declaration.property,
 
-         propertyValue = csstree.generate(declaration.value),
 
-         propertyPriority = (declaration.important ? 'important' : '');
 
-     return {
 
-         name: propertyName,
 
-         value: propertyValue,
 
-         priority: propertyPriority
 
-     };
 
- }
 
- /**
 
-  * Gets the CSS string of a style element
 
-  *
 
-  * @param {Object} element style element
 
-  * @return {String|Array} CSS string or empty array if no styles are set
 
-  */
 
- function getCssStr(elem) {
 
-     return elem.content[0].text || elem.content[0].cdata || [];
 
- }
 
- /**
 
-  * Sets the CSS string of a style element
 
-  *
 
-  * @param {Object} element style element
 
-  * @param {String} CSS string to be set
 
-  * @return {Object} reference to field with CSS
 
-  */
 
- function setCssStr(elem, css) {
 
-     // in case of cdata field
 
-     if(elem.content[0].cdata) {
 
-         elem.content[0].cdata = css;
 
-         return elem.content[0].cdata;
 
-     }
 
-     // in case of text field + if nothing was set yet
 
-     elem.content[0].text  = css;
 
-     return elem.content[0].text;
 
- }
 
- module.exports.flattenToSelectors = flattenToSelectors;
 
- module.exports.filterByMqs = filterByMqs;
 
- module.exports.filterByPseudos = filterByPseudos;
 
- module.exports.cleanPseudos = cleanPseudos;
 
- module.exports.compareSpecificity = compareSpecificity;
 
- module.exports.compareSimpleSelectorNode = compareSimpleSelectorNode;
 
- module.exports.sortSelectors = sortSelectors;
 
- module.exports.csstreeToStyleDeclaration = csstreeToStyleDeclaration;
 
- module.exports.getCssStr = getCssStr;
 
- module.exports.setCssStr = setCssStr;
 
 
  |