Demo for query storing
Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/svgo/lib/css-tools.js b/node_modules/svgo/lib/css-tools.js
new file mode 100644
index 0000000..6517892
--- /dev/null
+++ b/node_modules/svgo/lib/css-tools.js
@@ -0,0 +1,222 @@
+'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;