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.
		
		
		
		
			
				
					152 lines
				
				3.9 KiB
			
		
		
			
		
	
	
					152 lines
				
				3.9 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								var hasOwnProperty = Object.prototype.hasOwnProperty;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function isEqualSelectors(a, b) {
							 | 
						||
| 
								 | 
							
								    var cursor1 = a.head;
							 | 
						||
| 
								 | 
							
								    var cursor2 = b.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
							 | 
						||
| 
								 | 
							
								        cursor1 = cursor1.next;
							 | 
						||
| 
								 | 
							
								        cursor2 = cursor2.next;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return cursor1 === null && cursor2 === null;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function isEqualDeclarations(a, b) {
							 | 
						||
| 
								 | 
							
								    var cursor1 = a.head;
							 | 
						||
| 
								 | 
							
								    var cursor2 = b.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
							 | 
						||
| 
								 | 
							
								        cursor1 = cursor1.next;
							 | 
						||
| 
								 | 
							
								        cursor2 = cursor2.next;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return cursor1 === null && cursor2 === null;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function compareDeclarations(declarations1, declarations2) {
							 | 
						||
| 
								 | 
							
								    var result = {
							 | 
						||
| 
								 | 
							
								        eq: [],
							 | 
						||
| 
								 | 
							
								        ne1: [],
							 | 
						||
| 
								 | 
							
								        ne2: [],
							 | 
						||
| 
								 | 
							
								        ne2overrided: []
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var fingerprints = Object.create(null);
							 | 
						||
| 
								 | 
							
								    var declarations2hash = Object.create(null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (var cursor = declarations2.head; cursor; cursor = cursor.next)  {
							 | 
						||
| 
								 | 
							
								        declarations2hash[cursor.data.id] = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (var cursor = declarations1.head; cursor; cursor = cursor.next)  {
							 | 
						||
| 
								 | 
							
								        var data = cursor.data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (data.fingerprint) {
							 | 
						||
| 
								 | 
							
								            fingerprints[data.fingerprint] = data.important;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (declarations2hash[data.id]) {
							 | 
						||
| 
								 | 
							
								            declarations2hash[data.id] = false;
							 | 
						||
| 
								 | 
							
								            result.eq.push(data);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            result.ne1.push(data);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (var cursor = declarations2.head; cursor; cursor = cursor.next)  {
							 | 
						||
| 
								 | 
							
								        var data = cursor.data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (declarations2hash[data.id]) {
							 | 
						||
| 
								 | 
							
								            // if declarations1 has overriding declaration, this is not a difference
							 | 
						||
| 
								 | 
							
								            // but take in account !important - prev should be equal or greater than follow
							 | 
						||
| 
								 | 
							
								            if (hasOwnProperty.call(fingerprints, data.fingerprint) &&
							 | 
						||
| 
								 | 
							
								                Number(fingerprints[data.fingerprint]) >= Number(data.important)) {
							 | 
						||
| 
								 | 
							
								                result.ne2overrided.push(data);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                result.ne2.push(data);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function addSelectors(dest, source) {
							 | 
						||
| 
								 | 
							
								    source.each(function(sourceData) {
							 | 
						||
| 
								 | 
							
								        var newStr = sourceData.id;
							 | 
						||
| 
								 | 
							
								        var cursor = dest.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        while (cursor) {
							 | 
						||
| 
								 | 
							
								            var nextStr = cursor.data.id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (nextStr === newStr) {
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (nextStr > newStr) {
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            cursor = cursor.next;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dest.insert(dest.createItem(sourceData), cursor);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return dest;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// check if simpleselectors has no equal specificity and element selector
							 | 
						||
| 
								 | 
							
								function hasSimilarSelectors(selectors1, selectors2) {
							 | 
						||
| 
								 | 
							
								    var cursor1 = selectors1.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (cursor1 !== null) {
							 | 
						||
| 
								 | 
							
								        var cursor2 = selectors2.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        while (cursor2 !== null) {
							 | 
						||
| 
								 | 
							
								            if (cursor1.data.compareMarker === cursor2.data.compareMarker) {
							 | 
						||
| 
								 | 
							
								                return true;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            cursor2 = cursor2.next;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cursor1 = cursor1.next;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// test node can't to be skipped
							 | 
						||
| 
								 | 
							
								function unsafeToSkipNode(node) {
							 | 
						||
| 
								 | 
							
								    switch (node.type) {
							 | 
						||
| 
								 | 
							
								        case 'Rule':
							 | 
						||
| 
								 | 
							
								            // unsafe skip ruleset with selector similarities
							 | 
						||
| 
								 | 
							
								            return hasSimilarSelectors(node.prelude.children, this);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case 'Atrule':
							 | 
						||
| 
								 | 
							
								            // can skip at-rules with blocks
							 | 
						||
| 
								 | 
							
								            if (node.block) {
							 | 
						||
| 
								 | 
							
								                // unsafe skip at-rule if block contains something unsafe to skip
							 | 
						||
| 
								 | 
							
								                return node.block.children.some(unsafeToSkipNode, this);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case 'Declaration':
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // unsafe by default
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								    isEqualSelectors: isEqualSelectors,
							 | 
						||
| 
								 | 
							
								    isEqualDeclarations: isEqualDeclarations,
							 | 
						||
| 
								 | 
							
								    compareDeclarations: compareDeclarations,
							 | 
						||
| 
								 | 
							
								    addSelectors: addSelectors,
							 | 
						||
| 
								 | 
							
								    hasSimilarSelectors: hasSimilarSelectors,
							 | 
						||
| 
								 | 
							
								    unsafeToSkipNode: unsafeToSkipNode
							 | 
						||
| 
								 | 
							
								};
							 |