Skip to content

Commit

Permalink
style: Support resolving variables pointing to variables
Browse files Browse the repository at this point in the history
  • Loading branch information
robinlinden committed Nov 19, 2024
1 parent a8680ab commit 644c54d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
21 changes: 16 additions & 5 deletions style/styled_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cstring>
#include <iterator>
#include <optional>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -266,9 +267,9 @@ std::string_view StyledNode::get_raw_property(css::PropertyId property) const {
}

// If this is a var() we can easily expand here, do so.
if (it->second.starts_with("var(") && (it->second.find(')') != std::string::npos)) {
auto value = std::string_view{it->second};

auto value = std::string_view{it->second};
std::set<std::string_view> seen_variables{};
while (value.starts_with("var(") && (value.find(')') != std::string::npos)) {
// Remove "var(" from the start and ")" from the end. 5 characters in total.
auto var = value.substr(4, value.size() - 5);
auto [var_name, fallback] = util::split_once(var, ",");
Expand All @@ -283,10 +284,20 @@ std::string_view StyledNode::get_raw_property(css::PropertyId property) const {
return css::initial_value(property);
}

return *prop;
if (!prop->starts_with("var(")) {
return *prop;
}

seen_variables.insert(value);
if (seen_variables.contains(*prop)) {
spdlog::warn("Circular variable reference '{}'", *prop);
return css::initial_value(property);
}

value = *prop;
}

return it->second;
return value;
}

// NOLINTNEXTLINE(misc-no-recursion)
Expand Down
13 changes: 9 additions & 4 deletions style/styled_node_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,16 @@ int main() {
},
};

// TODO(robinlinden)
// expect_eq(styled_node.get_property<css::PropertyId::FontWeight>(), //
// style::FontWeight::bold());
expect_eq(styled_node.get_property<css::PropertyId::FontWeight>(), //
std::nullopt);
style::FontWeight::bold());

// Circular references are bad.
styled_node.custom_properties = {
{"--a", "var(--b)"},
{"--b", "var(--a)"},
};
expect_eq(styled_node.get_property<css::PropertyId::FontWeight>(), //
style::FontWeight::normal());
});

etest::test("var() with fallback, var exists", [] {
Expand Down

0 comments on commit 644c54d

Please sign in to comment.