mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-08 20:32:56 +03:00
LibWeb: Sort matched style rules by specificity, document order
If two rules have equal specificity, they should be applied in the order in which we encountered them.
This commit is contained in:
parent
fa5e8be31c
commit
384b5f15c9
Notes:
sideshowbarker
2024-07-19 05:41:10 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/384b5f15c94
@ -66,19 +66,25 @@ void StyleResolver::for_each_stylesheet(Callback callback) const
|
||||
}
|
||||
}
|
||||
|
||||
NonnullRefPtrVector<StyleRule> StyleResolver::collect_matching_rules(const Element& element) const
|
||||
Vector<MatchingRule> StyleResolver::collect_matching_rules(const Element& element) const
|
||||
{
|
||||
NonnullRefPtrVector<StyleRule> matching_rules;
|
||||
Vector<MatchingRule> matching_rules;
|
||||
|
||||
size_t style_sheet_index = 0;
|
||||
for_each_stylesheet([&](auto& sheet) {
|
||||
size_t rule_index = 0;
|
||||
for (auto& rule : sheet.rules()) {
|
||||
size_t selector_index = 0;
|
||||
for (auto& selector : rule.selectors()) {
|
||||
if (SelectorEngine::matches(selector, element)) {
|
||||
matching_rules.append(rule);
|
||||
matching_rules.append({ rule, style_sheet_index, rule_index, selector_index });
|
||||
break;
|
||||
}
|
||||
++selector_index;
|
||||
}
|
||||
++rule_index;
|
||||
}
|
||||
++style_sheet_index;
|
||||
});
|
||||
|
||||
#ifdef HTML_DEBUG
|
||||
@ -484,14 +490,22 @@ NonnullRefPtr<StyleProperties> StyleResolver::resolve_style(const Element& eleme
|
||||
|
||||
auto matching_rules = collect_matching_rules(element);
|
||||
|
||||
// FIXME: We need to look at the specificity of the matching *selector*, not just the matched *rule*!
|
||||
// FIXME: It's really awkward that NonnullRefPtrVector cannot be quick_sort()'ed
|
||||
quick_sort(reinterpret_cast<Vector<NonnullRefPtr<StyleRule>>&>(matching_rules), [&](auto& a, auto& b) {
|
||||
return a->selectors().first().specificity() < b->selectors().first().specificity();
|
||||
quick_sort(matching_rules, [&](MatchingRule& a, MatchingRule& b) {
|
||||
auto& a_selector = a.rule->selectors()[a.selector_index];
|
||||
auto& b_selector = b.rule->selectors()[b.selector_index];
|
||||
if (a_selector.specificity() < b_selector.specificity())
|
||||
return true;
|
||||
if (!(a_selector.specificity() == b_selector.specificity()))
|
||||
return false;
|
||||
if (a.style_sheet_index < b.style_sheet_index)
|
||||
return true;
|
||||
if (a.style_sheet_index > b.style_sheet_index)
|
||||
return false;
|
||||
return a.rule_index < b.rule_index;
|
||||
});
|
||||
|
||||
for (auto& rule : matching_rules) {
|
||||
for (auto& property : rule.declaration().properties()) {
|
||||
for (auto& match : matching_rules) {
|
||||
for (auto& property : match.rule->declaration().properties()) {
|
||||
set_property_expanding_shorthands(style, property.property_id, property.value, m_document);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,13 @@ class ParentNode;
|
||||
class StyleRule;
|
||||
class StyleSheet;
|
||||
|
||||
struct MatchingRule {
|
||||
RefPtr<StyleRule> rule;
|
||||
size_t style_sheet_index { 0 };
|
||||
size_t rule_index { 0 };
|
||||
size_t selector_index { 0 };
|
||||
};
|
||||
|
||||
class StyleResolver {
|
||||
public:
|
||||
explicit StyleResolver(Document&);
|
||||
@ -48,7 +55,7 @@ public:
|
||||
|
||||
NonnullRefPtr<StyleProperties> resolve_style(const Element&, const StyleProperties* parent_style) const;
|
||||
|
||||
NonnullRefPtrVector<StyleRule> collect_matching_rules(const Element&) const;
|
||||
Vector<MatchingRule> collect_matching_rules(const Element&) const;
|
||||
|
||||
static bool is_inherited_property(CSS::PropertyID);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user