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.
		
		
		
		
		
			
		
			
				
					
					
						
							78 lines
						
					
					
						
							2.4 KiB
						
					
					
				
			
		
		
	
	
							78 lines
						
					
					
						
							2.4 KiB
						
					
					
				| var Marker = require('../../tokenizer/marker');
 | |
| 
 | |
| var Selector = {
 | |
|   ADJACENT_SIBLING: '+',
 | |
|   DESCENDANT: '>',
 | |
|   DOT: '.',
 | |
|   HASH: '#',
 | |
|   NON_ADJACENT_SIBLING: '~',
 | |
|   PSEUDO: ':'
 | |
| };
 | |
| 
 | |
| var LETTER_PATTERN = /[a-zA-Z]/;
 | |
| var NOT_PREFIX = ':not(';
 | |
| var SEPARATOR_PATTERN = /[\s,\(>~\+]/;
 | |
| 
 | |
| function specificity(selector) {
 | |
|   var result = [0, 0, 0];
 | |
|   var character;
 | |
|   var isEscaped;
 | |
|   var isSingleQuoted;
 | |
|   var isDoubleQuoted;
 | |
|   var roundBracketLevel = 0;
 | |
|   var couldIntroduceNewTypeSelector;
 | |
|   var withinNotPseudoClass = false;
 | |
|   var wasPseudoClass = false;
 | |
|   var i, l;
 | |
| 
 | |
|   for (i = 0, l = selector.length; i < l; i++) {
 | |
|     character = selector[i];
 | |
| 
 | |
|     if (isEscaped) {
 | |
|       // noop
 | |
|     } else if (character == Marker.SINGLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
 | |
|       isSingleQuoted = true;
 | |
|     } else if (character == Marker.SINGLE_QUOTE && !isDoubleQuoted && isSingleQuoted) {
 | |
|       isSingleQuoted = false;
 | |
|     } else if (character == Marker.DOUBLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
 | |
|       isDoubleQuoted = true;
 | |
|     } else if (character == Marker.DOUBLE_QUOTE && isDoubleQuoted && !isSingleQuoted) {
 | |
|       isDoubleQuoted = false;
 | |
|     } else if (isSingleQuoted || isDoubleQuoted) {
 | |
|       continue;
 | |
|     } else if (roundBracketLevel > 0 && !withinNotPseudoClass) {
 | |
|       // noop
 | |
|     } else if (character == Marker.OPEN_ROUND_BRACKET) {
 | |
|       roundBracketLevel++;
 | |
|     } else if (character == Marker.CLOSE_ROUND_BRACKET && roundBracketLevel == 1) {
 | |
|       roundBracketLevel--;
 | |
|       withinNotPseudoClass = false;
 | |
|     } else if (character == Marker.CLOSE_ROUND_BRACKET) {
 | |
|       roundBracketLevel--;
 | |
|     } else if (character == Selector.HASH) {
 | |
|       result[0]++;
 | |
|     } else if (character == Selector.DOT || character == Marker.OPEN_SQUARE_BRACKET) {
 | |
|       result[1]++;
 | |
|     } else if (character == Selector.PSEUDO && !wasPseudoClass && !isNotPseudoClass(selector, i)) {
 | |
|       result[1]++;
 | |
|       withinNotPseudoClass = false;
 | |
|     } else if (character == Selector.PSEUDO) {
 | |
|       withinNotPseudoClass = true;
 | |
|     } else if ((i === 0 || couldIntroduceNewTypeSelector) && LETTER_PATTERN.test(character)) {
 | |
|       result[2]++;
 | |
|     }
 | |
| 
 | |
|     isEscaped = character == Marker.BACK_SLASH;
 | |
|     wasPseudoClass = character == Selector.PSEUDO;
 | |
|     couldIntroduceNewTypeSelector = !isEscaped && SEPARATOR_PATTERN.test(character);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| function isNotPseudoClass(selector, index) {
 | |
|   return selector.indexOf(NOT_PREFIX, index) === index;
 | |
| }
 | |
| 
 | |
| module.exports = specificity;
 |