Skip to content

Commit 1b57769

Browse files
committed
Split out cascade.
1 parent d1766a7 commit 1b57769

6 files changed

Lines changed: 296 additions & 259 deletions

File tree

cascade.js

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import {
2+
pseudoClasses,
3+
hasPseudoClass,
4+
parseCSSProperties,
5+
getNormalizedSuffix,
6+
isEffectivePseudoElem,
7+
} from "./css_parser.js";
8+
9+
import * as CSSwhat from "css-what";
10+
11+
export async function cascade(node, CSS) {
12+
//BUG: sometimes svg or some div nodeId=0
13+
const css = { "": {} };
14+
15+
try {
16+
var {
17+
inherited,
18+
inlineStyle,
19+
attributesStyle,
20+
matchedCSSRules,
21+
pseudoElements,
22+
} = await CSS.getMatchedStylesForNode({ nodeId: node.nodeId });
23+
24+
if (inherited) {
25+
for (let i = inherited.length - 1; i >= 0; i--) {
26+
const inheritedStyle = inherited[i];
27+
if (inheritedStyle.inlineStyle) {
28+
parseCSSProperties(
29+
inheritedStyle.inlineStyle.cssProperties,
30+
css[""],
31+
true
32+
);
33+
}
34+
if (inheritedStyle.matchedCSSRules) {
35+
for (const rule of inheritedStyle.matchedCSSRules) {
36+
if (rule.rule.origin !== "regular") continue;
37+
parseCSSProperties(rule.rule.style.cssProperties, css[""], true);
38+
}
39+
}
40+
}
41+
}
42+
43+
if (attributesStyle)
44+
parseCSSProperties(attributesStyle.cssProperties, css[""]);
45+
46+
for (const rule of matchedCSSRules) {
47+
if (rule.rule.origin !== "regular") continue;
48+
parseCSSProperties(rule.rule.style.cssProperties, css[""]);
49+
}
50+
51+
if (inlineStyle) parseCSSProperties(inlineStyle.cssProperties, css[""]);
52+
53+
for (const match of pseudoElements) {
54+
//match.pseudoType
55+
if (isEffectivePseudoElem(match, node)) {
56+
for (const rule of match.matches) {
57+
if (rule.rule.origin !== "regular") continue;
58+
const key = "::" + match.pseudoType;
59+
parseCSSProperties(
60+
rule.rule.style.cssProperties,
61+
(css[key] = css[key] || {})
62+
);
63+
}
64+
}
65+
}
66+
// normal css always not important
67+
/*
68+
Object.entries(css).forEach(([key, value]) => {
69+
Object.values(value).forEach((prop) => {
70+
prop.important = false;
71+
});
72+
});
73+
*/
74+
75+
node.css = css;
76+
} catch (error) {
77+
console.error("cascade", error);
78+
}
79+
}
80+
81+
export async function cascadePseudoClass(node, CSS) {
82+
try {
83+
const pseudoCss = {};
84+
//BUG: sometimes svg or some div nodeId=0
85+
/*
86+
const propertiesToTrack = [
87+
{ name: "color", value: "black" },
88+
//{ name: "color", value: "red" },
89+
];
90+
for (const [name, values] of Object.entries(computedStyles)) {
91+
for (const value of values) {
92+
propertiesToTrack.push({ name, value });
93+
}
94+
}
95+
console.log("nodeId", node.children[0].nodeId);
96+
97+
await CSS.trackComputedStyleUpdates({
98+
propertiesToTrack,
99+
});
100+
101+
console.log("takeComputedStyleUpdates");
102+
const p = CSS.takeComputedStyleUpdates();
103+
*/
104+
105+
await CSS.forcePseudoState({
106+
nodeId: node.nodeId,
107+
forcedPseudoClasses: pseudoClasses,
108+
});
109+
110+
/*
111+
console.log("await takeComputedStyleUpdates");
112+
const UpdatedNodeIds = await p;
113+
console.log("updated nodes", UpdatedNodeIds);
114+
115+
await CSS.trackComputedStyleUpdates({ propertiesToTrack: [] });
116+
*/
117+
118+
var { matchedCSSRules, pseudoElements } = await CSS.getMatchedStylesForNode(
119+
{ nodeId: node.nodeId }
120+
);
121+
122+
// TODO: pseudoVars for overridden
123+
// also cascade with non-pseudo and compare to ensure overridden
124+
125+
function iteratePseudo(rules) {
126+
for (const rule of rules) {
127+
if (rule.rule.origin !== "regular") continue;
128+
const matchingSelectors = rule.matchingSelectors.map(
129+
(i) => rule.rule.selectorList.selectors[i].text
130+
);
131+
for (const selector of matchingSelectors) {
132+
const parsedSelector = CSSwhat.parse(selector)[0];
133+
if (hasPseudoClass(parsedSelector)) {
134+
const suffix = getNormalizedSuffix(parsedSelector);
135+
if (!suffix) continue;
136+
parseCSSProperties(
137+
rule.rule.style.cssProperties,
138+
(pseudoCss[suffix] = pseudoCss[suffix] || {})
139+
);
140+
}
141+
}
142+
}
143+
}
144+
145+
iteratePseudo(matchedCSSRules);
146+
for (const match of pseudoElements) {
147+
if (isEffectivePseudoElem(match, node)) {
148+
iteratePseudo(match.matches);
149+
}
150+
}
151+
152+
// TODO: to solve hover a and show b problem, use nodeId as id and construct #a #b selector.
153+
// select right pseudo class by search the : and verify the selector prefix
154+
155+
await CSS.forcePseudoState({
156+
nodeId: node.nodeId,
157+
forcedPseudoClasses: [],
158+
});
159+
160+
/*
161+
Object.entries(pseudoCss).forEach(([key, value]) => {
162+
Object.values(value).forEach((prop) => {
163+
prop.important = true;
164+
});
165+
});
166+
*/
167+
168+
node.css = { ...node.css, ...pseudoCss };
169+
} catch (error) {
170+
console.error("cascade", error);
171+
}
172+
}

0 commit comments

Comments
 (0)