@@ -7,7 +7,8 @@ Computed const &Computed::initial() {
7
7
static Computed computed = [] {
8
8
Computed res{};
9
9
StyleProp::any ([&]<typename T>(Meta::Type<T>) {
10
- T{}.apply (res);
10
+ if constexpr (requires { T::initial (); })
11
+ T{}.apply (res);
11
12
});
12
13
return res;
13
14
}();
@@ -31,6 +32,61 @@ void Computer::_evalRule(Rule const &rule, Markup::Element const &el, MatchingRu
31
32
});
32
33
}
33
34
35
+ static Css::Content expandVariables (Cursor<Css::Sst> &cursor, Map<String, Css::Content> computedVars) {
36
+ // replacing the var with its value in the cascade
37
+ Css::Content computedDecl = {};
38
+ while (not cursor.ended ()) {
39
+ if (cursor.peek () == Css::Sst::FUNC and cursor.peek ().prefix == Css::Token::function (" var(" )) {
40
+
41
+ auto const varName = cursor->content [0 ].token .data ;
42
+ // if the variable is defined in the cascade
43
+ if (computedVars.has (varName)) {
44
+ computedDecl.pushBack (computedVars.get (varName));
45
+ } else {
46
+ if (cursor->content .len () > 2 ) {
47
+ // using the default value
48
+ Cursor<Css::Sst> cur = cursor->content ;
49
+ cur.next (2 );
50
+ eatWhitespace (cur);
51
+ auto defaultValue = expandVariables (cur, computedVars);
52
+ computedDecl.pushBack (defaultValue);
53
+ } else {
54
+ // invalid property
55
+ logWarn (" variable not found: {} {}" , varName, cursor->content );
56
+ }
57
+ }
58
+ cursor.next ();
59
+ } else if (cursor.peek () == Css::Sst::FUNC) {
60
+ Cursor<Css::Sst> cur = cursor->content ;
61
+ computedDecl.pushBack (cursor.peek ());
62
+ computedDecl[computedDecl.len () - 1 ].content = expandVariables (cur, computedVars);
63
+ cursor.next ();
64
+ } else {
65
+ computedDecl.pushBack (cursor.peek ());
66
+ cursor.next ();
67
+ }
68
+ }
69
+ return computedDecl;
70
+ }
71
+
72
+ static Res<StyleProp> resolve (DeferredProp const &prop, Map<String, Css::Content> computedVars) {
73
+ Cursor<Css::Sst> cursor = prop.value ;
74
+
75
+ auto computedDecl = expandVariables (cursor, computedVars);
76
+
77
+ // building the declaration
78
+ Css::Sst decl{Css::Sst::DECL};
79
+ decl.token = Css::Token::ident (prop.propName );
80
+ decl.content = computedDecl;
81
+
82
+ // parsing the declaration
83
+ Res<StyleProp> computed = parseDeclaration<StyleProp>(decl, false );
84
+ if (not computed) {
85
+ logWarn (" failed to parse declaration: {}" , computed.none ());
86
+ }
87
+ return computed;
88
+ }
89
+
34
90
Strong<Computed> Computer::computeFor (Computed const &parent, Markup::Element const &el) {
35
91
MatchingRules matchingRules;
36
92
@@ -51,6 +107,7 @@ Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element co
51
107
52
108
// Get the style attribute if any
53
109
auto styleAttr = el.getAttribute (Html::STYLE_ATTR);
110
+
54
111
StyleRule styleRule{
55
112
.selector = UNIVERSAL,
56
113
.props = parseDeclarations<StyleProp>(styleAttr ? *styleAttr : " " ),
@@ -62,7 +119,15 @@ Strong<Computed> Computer::computeFor(Computed const &parent, Markup::Element co
62
119
computed->inherit (parent);
63
120
64
121
for (auto const &styleRule : matchingRules) {
65
- for (auto const &prop : styleRule->props ) {
122
+ for (auto &prop : styleRule->props ) {
123
+ if (auto deferred = prop.is <DeferredProp>()) {
124
+ auto resolved = resolve (prop.unwrap <DeferredProp>(), computed->variables .cow ());
125
+
126
+ if (not resolved) {
127
+ continue ;
128
+ }
129
+ resolved.unwrap ().apply (*computed);
130
+ }
66
131
if (prop.important == Important::NO)
67
132
prop.apply (*computed);
68
133
}
0 commit comments