Spaces:
Configuration error
Configuration error
File size: 3,742 Bytes
a053984 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
const { hasOwnProperty } = Object.prototype;
export function isEqualSelectors(a, b) {
let cursor1 = a.head;
let 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;
}
export function isEqualDeclarations(a, b) {
let cursor1 = a.head;
let 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;
}
export function compareDeclarations(declarations1, declarations2) {
const result = {
eq: [],
ne1: [],
ne2: [],
ne2overrided: []
};
const fingerprints = Object.create(null);
const declarations2hash = Object.create(null);
for (let cursor = declarations2.head; cursor; cursor = cursor.next) {
declarations2hash[cursor.data.id] = true;
}
for (let cursor = declarations1.head; cursor; cursor = cursor.next) {
const 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 (let cursor = declarations2.head; cursor; cursor = cursor.next) {
const data = cursor.data;
if (declarations2hash[data.id]) {
// when declarations1 has an overriding declaration, this is not a difference
// unless no !important is used on prev and !important is used on the following
if (!hasOwnProperty.call(fingerprints, data.fingerprint) ||
(!fingerprints[data.fingerprint] && data.important)) {
result.ne2.push(data);
}
result.ne2overrided.push(data);
}
}
return result;
}
export function addSelectors(dest, source) {
source.forEach((sourceData) => {
const newStr = sourceData.id;
let cursor = dest.head;
while (cursor) {
const 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
export function hasSimilarSelectors(selectors1, selectors2) {
let cursor1 = selectors1.head;
while (cursor1 !== null) {
let 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
export 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;
}
|