aboutsummaryrefslogtreecommitdiff
path: root/node_modules/csso/lib/compressor/restructure/utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/csso/lib/compressor/restructure/utils.js')
-rw-r--r--node_modules/csso/lib/compressor/restructure/utils.js141
1 files changed, 141 insertions, 0 deletions
diff --git a/node_modules/csso/lib/compressor/restructure/utils.js b/node_modules/csso/lib/compressor/restructure/utils.js
new file mode 100644
index 00000000..70c92c51
--- /dev/null
+++ b/node_modules/csso/lib/compressor/restructure/utils.js
@@ -0,0 +1,141 @@
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function isEqualLists(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.value.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.value.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) {
+ return selectors1.some(function(a) {
+ return selectors2.some(function(b) {
+ return a.compareMarker === b.compareMarker;
+ });
+ });
+}
+
+// test node can't to be skipped
+function unsafeToSkipNode(node) {
+ switch (node.type) {
+ case 'Ruleset':
+ // unsafe skip ruleset with selector similarities
+ return hasSimilarSelectors(node.selector.selectors, this);
+
+ case 'Atrule':
+ // can skip at-rules with blocks
+ if (node.block) {
+ // non-stylesheet blocks are safe to skip since have no selectors
+ if (node.block.type !== 'StyleSheet') {
+ return false;
+ }
+
+ // unsafe skip at-rule if block contains something unsafe to skip
+ return node.block.rules.some(unsafeToSkipNode, this);
+ }
+ break;
+ }
+
+ // unsafe by default
+ return true;
+}
+
+module.exports = {
+ isEqualLists: isEqualLists,
+ isEqualDeclarations: isEqualDeclarations,
+ compareDeclarations: compareDeclarations,
+ addSelectors: addSelectors,
+ hasSimilarSelectors: hasSimilarSelectors,
+ unsafeToSkipNode: unsafeToSkipNode
+};