| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | 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    };};
 |