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.
		
		
		
		
			
				
					108 lines
				
				2.7 KiB
			
		
		
			
		
	
	
					108 lines
				
				2.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								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
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								};
							 |