142 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var csstree = require('css-tree');
 | 
						|
var parse = csstree.parse;
 | 
						|
var compress = require('./compress');
 | 
						|
var generate = csstree.generate;
 | 
						|
 | 
						|
function debugOutput(name, options, startTime, data) {
 | 
						|
    if (options.debug) {
 | 
						|
        console.error('## ' + name + ' done in %d ms\n', Date.now() - startTime);
 | 
						|
    }
 | 
						|
 | 
						|
    return data;
 | 
						|
}
 | 
						|
 | 
						|
function createDefaultLogger(level) {
 | 
						|
    var lastDebug;
 | 
						|
 | 
						|
    return function logger(title, ast) {
 | 
						|
        var line = title;
 | 
						|
 | 
						|
        if (ast) {
 | 
						|
            line = '[' + ((Date.now() - lastDebug) / 1000).toFixed(3) + 's] ' + line;
 | 
						|
        }
 | 
						|
 | 
						|
        if (level > 1 && ast) {
 | 
						|
            var css = generate(ast);
 | 
						|
 | 
						|
            // when level 2, limit css to 256 symbols
 | 
						|
            if (level === 2 && css.length > 256) {
 | 
						|
                css = css.substr(0, 256) + '...';
 | 
						|
            }
 | 
						|
 | 
						|
            line += '\n  ' + css + '\n';
 | 
						|
        }
 | 
						|
 | 
						|
        console.error(line);
 | 
						|
        lastDebug = Date.now();
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
function copy(obj) {
 | 
						|
    var result = {};
 | 
						|
 | 
						|
    for (var key in obj) {
 | 
						|
        result[key] = obj[key];
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
function buildCompressOptions(options) {
 | 
						|
    options = copy(options);
 | 
						|
 | 
						|
    if (typeof options.logger !== 'function' && options.debug) {
 | 
						|
        options.logger = createDefaultLogger(options.debug);
 | 
						|
    }
 | 
						|
 | 
						|
    return options;
 | 
						|
}
 | 
						|
 | 
						|
function runHandler(ast, options, handlers) {
 | 
						|
    if (!Array.isArray(handlers)) {
 | 
						|
        handlers = [handlers];
 | 
						|
    }
 | 
						|
 | 
						|
    handlers.forEach(function(fn) {
 | 
						|
        fn(ast, options);
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function minify(context, source, options) {
 | 
						|
    options = options || {};
 | 
						|
 | 
						|
    var filename = options.filename || '<unknown>';
 | 
						|
    var result;
 | 
						|
 | 
						|
    // parse
 | 
						|
    var ast = debugOutput('parsing', options, Date.now(),
 | 
						|
        parse(source, {
 | 
						|
            context: context,
 | 
						|
            filename: filename,
 | 
						|
            positions: Boolean(options.sourceMap)
 | 
						|
        })
 | 
						|
    );
 | 
						|
 | 
						|
    // before compress handlers
 | 
						|
    if (options.beforeCompress) {
 | 
						|
        debugOutput('beforeCompress', options, Date.now(),
 | 
						|
            runHandler(ast, options, options.beforeCompress)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    // compress
 | 
						|
    var compressResult = debugOutput('compress', options, Date.now(),
 | 
						|
        compress(ast, buildCompressOptions(options))
 | 
						|
    );
 | 
						|
 | 
						|
    // after compress handlers
 | 
						|
    if (options.afterCompress) {
 | 
						|
        debugOutput('afterCompress', options, Date.now(),
 | 
						|
            runHandler(compressResult, options, options.afterCompress)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    // generate
 | 
						|
    if (options.sourceMap) {
 | 
						|
        result = debugOutput('generate(sourceMap: true)', options, Date.now(), (function() {
 | 
						|
            var tmp = generate(compressResult.ast, { sourceMap: true });
 | 
						|
            tmp.map._file = filename; // since other tools can relay on file in source map transform chain
 | 
						|
            tmp.map.setSourceContent(filename, source);
 | 
						|
            return tmp;
 | 
						|
        }()));
 | 
						|
    } else {
 | 
						|
        result = debugOutput('generate', options, Date.now(), {
 | 
						|
            css: generate(compressResult.ast),
 | 
						|
            map: null
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
function minifyStylesheet(source, options) {
 | 
						|
    return minify('stylesheet', source, options);
 | 
						|
}
 | 
						|
 | 
						|
function minifyBlock(source, options) {
 | 
						|
    return minify('declarationList', source, options);
 | 
						|
}
 | 
						|
 | 
						|
module.exports = {
 | 
						|
    version: require('../package.json').version,
 | 
						|
 | 
						|
    // main methods
 | 
						|
    minify: minifyStylesheet,
 | 
						|
    minifyBlock: minifyBlock,
 | 
						|
 | 
						|
    // css syntax parser/walkers/generator/etc
 | 
						|
    syntax: Object.assign({
 | 
						|
        compress: compress
 | 
						|
    }, csstree)
 | 
						|
};
 |