95 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var generate = require('css-tree').generate;
 | |
| var specificity = require('./specificity');
 | |
| 
 | |
| var nonFreezePseudoElements = {
 | |
|     'first-letter': true,
 | |
|     'first-line': true,
 | |
|     'after': true,
 | |
|     'before': true
 | |
| };
 | |
| var nonFreezePseudoClasses = {
 | |
|     'link': true,
 | |
|     'visited': true,
 | |
|     'hover': true,
 | |
|     'active': true,
 | |
|     'first-letter': true,
 | |
|     'first-line': true,
 | |
|     'after': true,
 | |
|     'before': true
 | |
| };
 | |
| 
 | |
| module.exports = function freeze(node, usageData) {
 | |
|     var pseudos = Object.create(null);
 | |
|     var hasPseudo = false;
 | |
| 
 | |
|     node.prelude.children.each(function(simpleSelector) {
 | |
|         var tagName = '*';
 | |
|         var scope = 0;
 | |
| 
 | |
|         simpleSelector.children.each(function(node) {
 | |
|             switch (node.type) {
 | |
|                 case 'ClassSelector':
 | |
|                     if (usageData && usageData.scopes) {
 | |
|                         var classScope = usageData.scopes[node.name] || 0;
 | |
| 
 | |
|                         if (scope !== 0 && classScope !== scope) {
 | |
|                             throw new Error('Selector can\'t has classes from different scopes: ' + generate(simpleSelector));
 | |
|                         }
 | |
| 
 | |
|                         scope = classScope;
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case 'PseudoClassSelector':
 | |
|                     var name = node.name.toLowerCase();
 | |
| 
 | |
|                     if (!nonFreezePseudoClasses.hasOwnProperty(name)) {
 | |
|                         pseudos[':' + name] = true;
 | |
|                         hasPseudo = true;
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case 'PseudoElementSelector':
 | |
|                     var name = node.name.toLowerCase();
 | |
| 
 | |
|                     if (!nonFreezePseudoElements.hasOwnProperty(name)) {
 | |
|                         pseudos['::' + name] = true;
 | |
|                         hasPseudo = true;
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case 'TypeSelector':
 | |
|                     tagName = node.name.toLowerCase();
 | |
|                     break;
 | |
| 
 | |
|                 case 'AttributeSelector':
 | |
|                     if (node.flags) {
 | |
|                         pseudos['[' + node.flags.toLowerCase() + ']'] = true;
 | |
|                         hasPseudo = true;
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case 'WhiteSpace':
 | |
|                 case 'Combinator':
 | |
|                     tagName = '*';
 | |
|                     break;
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         simpleSelector.compareMarker = specificity(simpleSelector).toString();
 | |
|         simpleSelector.id = null; // pre-init property to avoid multiple hidden class
 | |
|         simpleSelector.id = generate(simpleSelector);
 | |
| 
 | |
|         if (scope) {
 | |
|             simpleSelector.compareMarker += ':' + scope;
 | |
|         }
 | |
| 
 | |
|         if (tagName !== '*') {
 | |
|             simpleSelector.compareMarker += ',' + tagName;
 | |
|         }
 | |
|     });
 | |
| 
 | |
|     // add property to all rule nodes to avoid multiple hidden class
 | |
|     node.pseudoSignature = hasPseudo && Object.keys(pseudos).sort().join(',');
 | |
| };
 |