home
readme
diff
tree
note
docs
0commit 35fdc3dd912205c066700c3731d390b63ce31ba4
1Author: lakefox <mason@lakefox.net>
2Date: Fri Jan 16 15:26:06 2026 -0700
3
4 var()
5
6diff --git a/include/grim.h b/include/grim.h
7index 7b1c532..19b86a2 100755
8--- a/include/grim.h
9+++ b/include/grim.h
10@@ -193,6 +193,7 @@ class Node {
11 void setAttribute(const std::string& name, const std::string& value);
12 void deleteAttribute(const std::string& name);
13 std::string getAttribute(const std::string& name) const;
14+ bool hasAttribute(const std::string& name) const;
15
16 const std::unordered_map<std::string, std::string>& getAttributes() const;
17 std::vector<std::string> getAttributeKeys();
18@@ -289,6 +290,15 @@ class IndexedMap {
19 }
20 }
21
22+ bool contains(std::string key) {
23+ for (size_t i = 0; i < map.size(); i++) {
24+ if (map[i].first == key) {
25+ return true;
26+ }
27+ }
28+ return false;
29+ }
30+
31 size_t index(std::string key) {
32 for (size_t i = 0; i < map.size(); i++) {
33 if (map[i].first == key) {
34@@ -320,7 +330,7 @@ class Style {
35 public:
36 std::unordered_map<std::string, std::vector<size_t>> basemap{};
37
38- std::string name;
39+ std::string name; // remove
40 std::vector<std::vector<std::string>> selector{};
41
42 std::unordered_map<KeyType, std::vector<Unit>> properties{};
43diff --git a/playground/window.cc b/playground/window.cc
44index e8ec151..5d54e8c 100644
45--- a/playground/window.cc
46+++ b/playground/window.cc
47@@ -10,8 +10,8 @@ int main() {
48 "<html width=\"\">"
49 "<head>"
50 "<title>This is a simple test</title>"
51- "<link rel=\"stylesheet\" href=\'tests/style.css\'/>"
52- "<style>h1 {background: red;}</style>"
53+ "<!--<link rel=\"stylesheet\" href=\'tests/style.css\'/>-->"
54+ "<style>:root {--test: 10px;} h1 {--test2: 10px; background: red;}</style>"
55 "</head>"
56 "<body>"
57 "<h1 id=\"h1Tag\">Header</h1>"
58@@ -50,7 +50,7 @@ int main() {
59
60 document.children[0].cacheWidth(1000);
61
62- std::vector<Unit> units = getUnit(&window.CSS, "attr(width px, 10px)");
63+ std::vector<Unit> units = getUnit(&window.CSS, "var(--test)");
64
65- std::cout << UnitLengthValue(&document.children[0], &window.CSS, units, 0, units.size()) << std::endl;
66+ std::cout << UnitLengthValue(&document.children[0], &window.CSS.children[0], units, 0, units.size()) << std::endl;
67 }
68diff --git a/src/grim.cc b/src/grim.cc
69index e18d42c..bbd3df0 100755
70--- a/src/grim.cc
71+++ b/src/grim.cc
72@@ -13,6 +13,7 @@
73 #include <stdexcept>
74 #include <limits>
75 #include <cmath>
76+#include <string>
77
78 // +------------------------------------------------------+
79 // |(TOC) Table of contents |
80@@ -135,6 +136,10 @@ std::string Node::getAttribute(const std::string& name) const {
81 }
82 }
83
84+bool Node::hasAttribute(const std::string& name) const {
85+ return attributes.contains(name) || DEFAULT_ATTRIBUTE_VALUES.contains(name);
86+}
87+
88 std::vector<std::string> Node::getAttributeKeys() {
89 std::vector<std::string> keys;
90
91@@ -725,6 +730,7 @@ std::vector<std::string> parseNodeParts(Node* node) {
92 }
93
94 parts.push_back("*");
95+ parts.push_back(":root");
96
97 return parts;
98 }
99@@ -947,8 +953,6 @@ float UnitLengthValue(Node* n, Style* style, const std::vector<Unit>& units, siz
100 float sum = 0;
101 UnitType op = UnitType::ADD;
102
103- std::cout << "CALL START: " << start << " END: " << end << std::endl;
104-
105 for (size_t i = start; i < end; i++) {
106 Unit unit = units[i];
107 UnitType type = unit.type;
108@@ -962,6 +966,7 @@ float UnitLengthValue(Node* n, Style* style, const std::vector<Unit>& units, siz
109 std::vector<Range> extracted;
110 UnitType ut;
111 std::string s = "";
112+ bool b = false;
113
114 switch (type) {
115 case UnitType::ADD:
116@@ -1297,9 +1302,10 @@ float UnitLengthValue(Node* n, Style* style, const std::vector<Unit>& units, siz
117 extracted = extractUnits(units, i+1, i+1+unit.value.INT);
118
119 if (units[extracted[0].start].type == UnitType::VAR) {
120+ b = n->hasAttribute(style->variables.key(units[extracted[0].start].value.INT));
121 s = n->getAttribute(style->variables.key(units[extracted[0].start].value.INT));
122
123- if (!s.empty()) {
124+ if (!s.empty() && b) {
125 // attr(size px, 10)
126 // s = n->getAttribute(size) size="20"
127 std::vector<Unit> us = getUnit(style, s);
128@@ -1317,11 +1323,44 @@ float UnitLengthValue(Node* n, Style* style, const std::vector<Unit>& units, siz
129 value = UnitLengthValue(n, style, us, 0, us.size());
130 } else if (extracted.size() == 3) {
131 // Default value
132- value = UnitLengthValue(n, style, units, extracted[2].start, extracted[2].end);
133+ value = UnitLengthValue(n, style, units, extracted[6].start, extracted[2].end);
134+ }
135+ }
136+
137+ i += unit.value.INT;
138+ break;
139+ case UnitType::VAR:
140+ extracted = extractUnits(units, i+1, i+1+unit.value.INT);
141+
142+ if (units[extracted[0].start].type == UnitType::VAR) {
143+ // Variables flow down during processing so theres no need to check above
144+ std::vector<Unit> us = style->variables.at(units[extracted[0].start].value.INT);
145+
146+ if (us.size() > 0) {
147+ value = UnitLengthValue(n, style, us, 0, us.size());
148+ } else if (extracted.size() == 2) {
149+ // Default value
150+ value = UnitLengthValue(n, style, units, extracted[1].start, extracted[1].end);
151 }
152 }
153
154 i += unit.value.INT;
155+ break;
156+
157+
158+
159+
160+
161+
162+
163+
164+ // Why not make this just get unit value and return a unit?
165+
166+
167+
168+
169+
170+
171
172 // Need to add variable injection and group handling
173 }
174@@ -1344,7 +1383,6 @@ float UnitLengthValue(Node* n, Style* style, const std::vector<Unit>& units, siz
175 }
176 }
177
178- std::cout << "SUM: " << sum << std::endl;
179 return sum;
180 }
181
182@@ -1524,11 +1562,9 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
183 }
184 }
185
186-
187-
188 size_t i = 0;
189- for (auto p : parts) {
190- if (p[0] == '*') {
191+ for (std::string p : parts) {
192+ if (p[0] == '*' || p == ":root") {
193 matched = true;
194 } else if (i == 0 && p[0] != '#' && p[0] != '.' && p[0] != '[' && p[0] != ':') {
195 matched = tagName == p;
196@@ -1572,7 +1608,7 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
197 matched = testSelector(node, next);
198 } else if (p.starts_with(":where")) {
199 // Per specification where and is differ in specificity only
200- // however, grim does not support specificity
201+ // however, grim does not support specificity at this time
202 // https://developer.mozilla.org/en-US/docs/Web/CSS/:is#difference_between_is_and_where
203 matched = testSelector(node, next);
204 } else if (p.starts_with(":not")) {
205diff --git a/src/parser.cc b/src/parser.cc
206index 8b51153..e5f027a 100755
207--- a/src/parser.cc
208+++ b/src/parser.cc
209@@ -97,7 +97,7 @@ std::unordered_map<std::string, std::string> parseAttributes(std::string_view to
210 }
211
212 if (trimmedValue.length() == 0) {
213- trimmedValue = "true";
214+ trimmedValue = "";
215 }
216
217 attrs[trimmedName] = trimmedValue;