You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							107 lines
						
					
					
						
							2.7 KiB
						
					
					
				
			
		
		
	
	
							107 lines
						
					
					
						
							2.7 KiB
						
					
					
				var List = require('css-tree').List; | 
						|
var resolveKeyword = require('css-tree').keyword; | 
						|
var hasOwnProperty = Object.prototype.hasOwnProperty; | 
						|
var walk = require('css-tree').walk; | 
						|
 | 
						|
function addRuleToMap(map, item, list, single) { | 
						|
    var node = item.data; | 
						|
    var name = resolveKeyword(node.name).basename; | 
						|
    var id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null); | 
						|
 | 
						|
    if (!hasOwnProperty.call(map, name)) { | 
						|
        map[name] = Object.create(null); | 
						|
    } | 
						|
 | 
						|
    if (single) { | 
						|
        delete map[name][id]; | 
						|
    } | 
						|
 | 
						|
    if (!hasOwnProperty.call(map[name], id)) { | 
						|
        map[name][id] = new List(); | 
						|
    } | 
						|
 | 
						|
    map[name][id].append(list.remove(item)); | 
						|
} | 
						|
 | 
						|
function relocateAtrules(ast, options) { | 
						|
    var collected = Object.create(null); | 
						|
    var topInjectPoint = null; | 
						|
 | 
						|
    ast.children.each(function(node, item, list) { | 
						|
        if (node.type === 'Atrule') { | 
						|
            var name = resolveKeyword(node.name).basename; | 
						|
 | 
						|
            switch (name) { | 
						|
                case 'keyframes': | 
						|
                    addRuleToMap(collected, item, list, true); | 
						|
                    return; | 
						|
 | 
						|
                case 'media': | 
						|
                    if (options.forceMediaMerge) { | 
						|
                        addRuleToMap(collected, item, list, false); | 
						|
                        return; | 
						|
                    } | 
						|
                    break; | 
						|
            } | 
						|
 | 
						|
            if (topInjectPoint === null && | 
						|
                name !== 'charset' && | 
						|
                name !== 'import') { | 
						|
                topInjectPoint = item; | 
						|
            } | 
						|
        } else { | 
						|
            if (topInjectPoint === null) { | 
						|
                topInjectPoint = item; | 
						|
            } | 
						|
        } | 
						|
    }); | 
						|
 | 
						|
    for (var atrule in collected) { | 
						|
        for (var id in collected[atrule]) { | 
						|
            ast.children.insertList( | 
						|
                collected[atrule][id], | 
						|
                atrule === 'media' ? null : topInjectPoint | 
						|
            ); | 
						|
        } | 
						|
    } | 
						|
}; | 
						|
 | 
						|
function isMediaRule(node) { | 
						|
    return node.type === 'Atrule' && node.name === 'media'; | 
						|
} | 
						|
 | 
						|
function processAtrule(node, item, list) { | 
						|
    if (!isMediaRule(node)) { | 
						|
        return; | 
						|
    } | 
						|
 | 
						|
    var prev = item.prev && item.prev.data; | 
						|
 | 
						|
    if (!prev || !isMediaRule(prev)) { | 
						|
        return; | 
						|
    } | 
						|
 | 
						|
    // merge @media with same query | 
						|
    if (node.prelude && | 
						|
        prev.prelude && | 
						|
        node.prelude.id === prev.prelude.id) { | 
						|
        prev.block.children.appendList(node.block.children); | 
						|
        list.remove(item); | 
						|
 | 
						|
        // TODO: use it when we can refer to several points in source | 
						|
        // prev.loc = { | 
						|
        //     primary: prev.loc, | 
						|
        //     merged: node.loc | 
						|
        // }; | 
						|
    } | 
						|
} | 
						|
 | 
						|
module.exports = function rejoinAtrule(ast, options) { | 
						|
    relocateAtrules(ast, options); | 
						|
 | 
						|
    walk(ast, { | 
						|
        visit: 'Atrule', | 
						|
        reverse: true, | 
						|
        enter: processAtrule | 
						|
    }); | 
						|
};
 | 
						|
 |