Skip to content

Commit

Permalink
vaev-syle: Fix cascade order for useragent stylesheets.
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepy-monax committed Nov 26, 2024
1 parent bf16521 commit 6f1a635
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/vaev-driver/fetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ Res<Strong<Markup::Document>> fetchDocument(Mime::Url const &url) {
}
}

Res<Style::StyleSheet> fetchStylesheet(Mime::Url url) {
Res<Style::StyleSheet> fetchStylesheet(Mime::Url url, Style::Origin origin) {
auto file = try$(Sys::File::open(url));
auto buf = try$(Io::readAllUtf8(file));
Io::SScan s{buf};
return Ok(Style::StyleSheet::parse(s));
return Ok(Style::StyleSheet::parse(s, origin));
}

} // namespace Vaev::Driver
2 changes: 1 addition & 1 deletion src/vaev-driver/fetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Vaev::Driver {

Res<Style::StyleSheet> fetchStylesheet(Mime::Url url);
Res<Style::StyleSheet> fetchStylesheet(Mime::Url url, Style::Origin origin = Style::Origin::AUTHOR);

Res<Strong<Markup::Document>> fetchDocument(Mime::Url const &url);

Expand Down
6 changes: 3 additions & 3 deletions src/vaev-driver/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static void _collectStyle(Markup::Node const &node, Style::StyleBook &sb) {
return;
}

auto sheet = fetchStylesheet(url.take());
auto sheet = fetchStylesheet(url.take(), Style::Origin::AUTHOR);
if (not sheet) {
logWarn("failed to fetch stylesheet: {}", sheet);
return;
Expand All @@ -54,7 +54,7 @@ static void _collectStyle(Markup::Node const &node, Style::StyleBook &sb) {
RenderResult render(Markup::Document const &dom, Style::Media const &media, Layout::Viewport viewport) {
Style::StyleBook stylebook;
stylebook.add(
fetchStylesheet("bundle://vaev-driver/user-agent.css"_url)
fetchStylesheet("bundle://vaev-driver/user-agent.css"_url, Style::Origin::USER_AGENT)
.take("user agent stylesheet not available")
);

Expand Down Expand Up @@ -113,7 +113,7 @@ RenderResult render(Markup::Document const &dom, Style::Media const &media, Layo
Vec<Strong<Scene::Page>> print(Markup::Document const &dom, Style::Media const &media) {
Style::StyleBook stylebook;
stylebook.add(
fetchStylesheet("bundle://vaev-driver/user-agent.css"_url)
fetchStylesheet("bundle://vaev-driver/user-agent.css"_url, Style::Origin::USER_AGENT)
.take("user agent stylesheet not available")
);

Expand Down
8 changes: 5 additions & 3 deletions src/vaev-style/computer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void Computer::_evalRule(Rule const &rule, Markup::Element const &el, MatchingRu
});
}

// https://drafts.csswg.org/css-cascade/#cascade-origin
Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element const &el) {
MatchingRules matchingRules;

Expand All @@ -42,10 +43,12 @@ Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element co
}
}

// Sort rules by specificity
// Sort origin and specificity
stableSort(
matchingRules,
[](auto const &a, auto const &b) {
if (a->origin != b->origin)
return a->origin <=> b->origin;
return spec(a->selector) <=> spec(b->selector);
}
);
Expand All @@ -54,7 +57,6 @@ Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element co
auto styleAttr = el.getAttribute(Html::STYLE_ATTR);

StyleRule styleRule{
.selector = UNIVERSAL,
.props = parseDeclarations<StyleProp>(styleAttr ? *styleAttr : ""),
};
matchingRules.pushBack(&styleRule);
Expand All @@ -73,7 +75,7 @@ Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element co
}
}

for (auto const &prop : importantProps)
for (auto const &prop : iterRev(importantProps))
prop->apply(*computed);

return computed;
Expand Down
23 changes: 23 additions & 0 deletions src/vaev-style/origin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <karm-base/base.h>

namespace Vaev::Style {

// https://drafts.csswg.org/css-cascade/#origin
enum struct Origin {
// NOTE: The order of these values is important
USER_AGENT,
USER,
AUTHOR,
};

static inline std::strong_ordering operator<=>(Origin a, Origin b) {
return static_cast<u8>(a) <=> static_cast<u8>(b);
}

static inline bool operator==(Origin a, Origin b) {
return static_cast<u8>(a) == static_cast<u8>(b);
}

} // namespace Vaev::Style
7 changes: 4 additions & 3 deletions src/vaev-style/rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void StyleRule::repr(Io::Emit &e) const {
e(")");
}

StyleRule StyleRule::parse(Css::Sst const &sst) {
StyleRule StyleRule::parse(Css::Sst const &sst, Origin origin) {
if (sst != Css::Sst::RULE)
panic("expected rule");

Expand All @@ -49,6 +49,7 @@ StyleRule StyleRule::parse(Css::Sst const &sst) {
}
}

res.origin = origin;
return res;
}

Expand Down Expand Up @@ -128,7 +129,7 @@ void Rule::repr(Io::Emit &e) const {
});
}

Rule Rule::parse(Css::Sst const &sst) {
Rule Rule::parse(Css::Sst const &sst, Origin origin) {
if (sst != Css::Sst::RULE)
panic("expected rule");

Expand All @@ -140,7 +141,7 @@ Rule Rule::parse(Css::Sst const &sst) {
else if (tok.data == "@font-face")
return FontFaceRule::parse(sst);
else
return StyleRule::parse(sst);
return StyleRule::parse(sst, origin);
}

} // namespace Vaev::Style
8 changes: 5 additions & 3 deletions src/vaev-style/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "fonts.h"
#include "media.h"
#include "origin.h"
#include "select.h"
#include "styles.h"

Expand All @@ -11,16 +12,17 @@ struct Rule;

// https://www.w3.org/TR/cssom-1/#the-cssstylerule-interface
struct StyleRule {
Selector selector;
Selector selector = UNIVERSAL;
Vec<StyleProp> props;
Origin origin = Origin::AUTHOR;

void repr(Io::Emit &e) const;

bool match(Markup::Element const &el) const {
return selector.match(el);
}

static StyleRule parse(Css::Sst const &sst);
static StyleRule parse(Css::Sst const &sst, Origin origin = Origin::AUTHOR);
};

// https://www.w3.org/TR/cssom-1/#the-cssimportrule-interface
Expand Down Expand Up @@ -65,7 +67,7 @@ struct Rule : public _Rule {

void repr(Io::Emit &e) const;

static Rule parse(Css::Sst const &sst);
static Rule parse(Css::Sst const &sst, Origin origin = Origin::AUTHOR);
};

} // namespace Vaev::Style
5 changes: 3 additions & 2 deletions src/vaev-style/stylesheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ void StyleSheet::repr(Io::Emit &e) const {
e(")");
}

StyleSheet StyleSheet::parse(Css::Sst const &sst) {
StyleSheet StyleSheet::parse(Css::Sst const &sst, Origin origin) {
if (sst != Css::Sst::LIST)
panic("expected list");

Style::StyleSheet res;
for (auto const &item : sst.content) {
if (item == Css::Sst::RULE) {
res.rules.pushBack(Rule::parse(item));
res.rules.pushBack(Rule::parse(item, origin));
} else {
logWarn("unexpected item in stylesheet: {}", item.type);
}
}

res.origin = origin;
return res;
}

Expand Down
11 changes: 8 additions & 3 deletions src/vaev-style/stylesheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ struct StyleSheet {
Mime::Url href = ""_url;
Str title = "";
Vec<Rule> rules;
Origin origin = Origin::AUTHOR;

void repr(Io::Emit &e) const;

static StyleSheet parse(Css::Sst const &sst);
static StyleSheet parse(Css::Sst const &sst, Origin origin = Origin::AUTHOR);

static Style::StyleSheet parse(Io::SScan &s) {
static Style::StyleSheet parse(Io::SScan &s, Origin origin = Origin::AUTHOR) {
Css::Lexer lex{s};
Css::Sst sst = consumeRuleList(lex, true);
return parse(sst);
return parse(sst, origin);
}

void add(Rule &&rule) {
rules.pushBack(std::move(rule));
}
};

Expand Down
2 changes: 0 additions & 2 deletions src/vaev-view/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ struct View : public Ui::View<View> {

paint->paint(g, rect.offset(-bound().xy).cast<f64>());
if (Ui::debugShowLayoutBounds) {
logDebug("layout tree: {}", layout);
logDebug("paint tree: {}", paint);
Layout::wireframe(*layout, g);
}

Expand Down

0 comments on commit 6f1a635

Please sign in to comment.