Demo for query storing

Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/csso/lib/compress.js b/node_modules/csso/lib/compress.js
new file mode 100644
index 0000000..17be39b
--- /dev/null
+++ b/node_modules/csso/lib/compress.js
@@ -0,0 +1,197 @@
+var List = require('css-tree').List;
+var clone = require('css-tree').clone;
+var usageUtils = require('./usage');
+var clean = require('./clean');
+var replace = require('./replace');
+var restructure = require('./restructure');
+var walk = require('css-tree').walk;
+
+function readChunk(children, specialComments) {
+    var buffer = new List();
+    var nonSpaceTokenInBuffer = false;
+    var protectedComment;
+
+    children.nextUntil(children.head, function(node, item, list) {
+        if (node.type === 'Comment') {
+            if (!specialComments || node.value.charAt(0) !== '!') {
+                list.remove(item);
+                return;
+            }
+
+            if (nonSpaceTokenInBuffer || protectedComment) {
+                return true;
+            }
+
+            list.remove(item);
+            protectedComment = node;
+            return;
+        }
+
+        if (node.type !== 'WhiteSpace') {
+            nonSpaceTokenInBuffer = true;
+        }
+
+        buffer.insert(list.remove(item));
+    });
+
+    return {
+        comment: protectedComment,
+        stylesheet: {
+            type: 'StyleSheet',
+            loc: null,
+            children: buffer
+        }
+    };
+}
+
+function compressChunk(ast, firstAtrulesAllowed, num, options) {
+    options.logger('Compress block #' + num, null, true);
+
+    var seed = 1;
+
+    if (ast.type === 'StyleSheet') {
+        ast.firstAtrulesAllowed = firstAtrulesAllowed;
+        ast.id = seed++;
+    }
+
+    walk(ast, {
+        visit: 'Atrule',
+        enter: function markScopes(node) {
+            if (node.block !== null) {
+                node.block.id = seed++;
+            }
+        }
+    });
+    options.logger('init', ast);
+
+    // remove redundant
+    clean(ast, options);
+    options.logger('clean', ast);
+
+    // replace nodes for shortened forms
+    replace(ast, options);
+    options.logger('replace', ast);
+
+    // structure optimisations
+    if (options.restructuring) {
+        restructure(ast, options);
+    }
+
+    return ast;
+}
+
+function getCommentsOption(options) {
+    var comments = 'comments' in options ? options.comments : 'exclamation';
+
+    if (typeof comments === 'boolean') {
+        comments = comments ? 'exclamation' : false;
+    } else if (comments !== 'exclamation' && comments !== 'first-exclamation') {
+        comments = false;
+    }
+
+    return comments;
+}
+
+function getRestructureOption(options) {
+    if ('restructure' in options) {
+        return options.restructure;
+    }
+
+    return 'restructuring' in options ? options.restructuring : true;
+}
+
+function wrapBlock(block) {
+    return new List().appendData({
+        type: 'Rule',
+        loc: null,
+        prelude: {
+            type: 'SelectorList',
+            loc: null,
+            children: new List().appendData({
+                type: 'Selector',
+                loc: null,
+                children: new List().appendData({
+                    type: 'TypeSelector',
+                    loc: null,
+                    name: 'x'
+                })
+            })
+        },
+        block: block
+    });
+}
+
+module.exports = function compress(ast, options) {
+    ast = ast || { type: 'StyleSheet', loc: null, children: new List() };
+    options = options || {};
+
+    var compressOptions = {
+        logger: typeof options.logger === 'function' ? options.logger : function() {},
+        restructuring: getRestructureOption(options),
+        forceMediaMerge: Boolean(options.forceMediaMerge),
+        usage: options.usage ? usageUtils.buildIndex(options.usage) : false
+    };
+    var specialComments = getCommentsOption(options);
+    var firstAtrulesAllowed = true;
+    var input;
+    var output = new List();
+    var chunk;
+    var chunkNum = 1;
+    var chunkChildren;
+
+    if (options.clone) {
+        ast = clone(ast);
+    }
+
+    if (ast.type === 'StyleSheet') {
+        input = ast.children;
+        ast.children = output;
+    } else {
+        input = wrapBlock(ast);
+    }
+
+    do {
+        chunk = readChunk(input, Boolean(specialComments));
+        compressChunk(chunk.stylesheet, firstAtrulesAllowed, chunkNum++, compressOptions);
+        chunkChildren = chunk.stylesheet.children;
+
+        if (chunk.comment) {
+            // add \n before comment if there is another content in output
+            if (!output.isEmpty()) {
+                output.insert(List.createItem({
+                    type: 'Raw',
+                    value: '\n'
+                }));
+            }
+
+            output.insert(List.createItem(chunk.comment));
+
+            // add \n after comment if chunk is not empty
+            if (!chunkChildren.isEmpty()) {
+                output.insert(List.createItem({
+                    type: 'Raw',
+                    value: '\n'
+                }));
+            }
+        }
+
+        if (firstAtrulesAllowed && !chunkChildren.isEmpty()) {
+            var lastRule = chunkChildren.last();
+
+            if (lastRule.type !== 'Atrule' ||
+               (lastRule.name !== 'import' && lastRule.name !== 'charset')) {
+                firstAtrulesAllowed = false;
+            }
+        }
+
+        if (specialComments !== 'exclamation') {
+            specialComments = false;
+        }
+
+        output.appendList(chunkChildren);
+    } while (!input.isEmpty());
+
+    return {
+        ast: ast
+    };
+};