forked from kamicane/art
-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathSheet.Cascade.js
95 lines (82 loc) · 2.47 KB
/
Sheet.Cascade.js
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
var Slick = require('./slick/Source/slick').Slick;
var CSS = require('./sheet.js/Source/SheetParser.CSS').SheetParser.CSS;
function calculateSpecificity(expression){
var specificity = 0;
for (var i = 0, l = expression.length; i < l; i++){
var part = expression[i];
if (part.id) specificity += 10000;
if (part.classes) specificity += part.classes.length * 1000;
if (part.pseudos) specificity += part.pseudos.length * 1000;
if (part.attributes) specificity += part.attributes.length * 1000;
if (part.tag && part.tag != '*') specificity += 100;
}
return specificity;
};
function sortRules(rules){
rules.sort(function(a,b){
if (a.specificity < b.specificity)
return -1;
else if (a.specificity > b.specificity)
return 1;
return 0;
});
};
function nodeContent(node){
var n = node.firstChild, text = '';
while (n){
text += n.nodeValue;
n = n.nextSibling;
}
return text;
}
var SheetCascade = function(){
this.rules = [];
this.cssRules = [];
};
SheetCascade.prototype = {
addSheet: function(sheet){
var rules = sheet.cssRules || CSS.parse(sheet.innerHTML || nodeContent(sheet) || sheet);
for (var i = 0, l = rules.length; i < l; i++){
var rule = rules[i];
this.cssRules.push(rule);
this.addRule(rule.selectorText, rule.style);
}
},
addRule: function(selector, style){
var parsed = Slick.parse(selector);
if (!parsed) return;
var expressions = parsed.expressions;
for (var i = 0, l = expressions.length; i < l; i++){
var expression = expressions[i],
specificity = calculateSpecificity(expression) + this.rules.length;
this.rules.push({
specificity: specificity,
expression: expression,
style: style
});
}
this.sorted = false;
},
getStyle: function(node){
var style = {};
this.applyStyle(node, style);
return style;
},
applyStyle: function(node, targetStyle){
var rules = this.rules;
if (!this.sorted){ sortRules(rules); this.sorted = true; }
for (var i = 0, l = rules.length; i < l; i++){
var rule = rules[i];
if (Slick.match(node, { Slick: true, expressions: [rule.expression] })){
var ruleStyle = rule.style;
for (var name in ruleStyle) targetStyle[name] = ruleStyle[name];
}
}
var cssText = node.getAttribute('style');
if (cssText){
var inlineStyle = CSS.parse(cssText);
for (var name in inlineStyle) targetStyle[name] = inlineStyle[name];
}
}
};
exports.SheetCascade = SheetCascade;