home readme diff tree note docs

0commit abf4e7fe9546106c00ce8e8f1ebab94fde4d3310
1Author: lakefox <mason@lakefox.net>
2Date:   Sun Jan 11 15:30:48 2026 -0700
3
4    getUnit parses variables and strings. Tests updated
5
6diff --git a/Makefile b/Makefile
7index c295710..32afc3f 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -1,5 +1,14 @@
11 # --- Variables ---
12 CCFLAGS = -Wall -Wextra -std=c++2b -g -O0 -fsanitize=address,undefined -fno-omit-frame-pointer
13+# -O2 -Wall -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough \
14+# -Werror=format-security \
15+# -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \
16+# -D_GLIBCXX_ASSERTIONS \
17+# -fstrict-flex-arrays=3 \
18+# -fstack-clash-protection -fstack-protector-strong \
19+# -Wl,-z,nodlopen -Wl,-z,noexecstack \
20+# -Wl,-z,relro -Wl,-z,now \
21+# -Wl,--as-needed -Wl,--no-copy-dt-needed-entries
22 CC = clang++
23 
24 .PHONY: all clean all_tests
25diff --git a/include/grim.h b/include/grim.h
26index 5615570..07e5ce3 100755
27--- a/include/grim.h
28+++ b/include/grim.h
29@@ -90,6 +90,7 @@ enum class UnitType : short {
30 		CALC, MIN, MAX, CLAMP, ROUND, MOD, PROGRESS, REMD, POW, SQRT, HYPOT, LOG, EXP, ABS,
31 		SIGN, SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2, VAR,
32 		BLUR, BRIGHTNESS, CONTRAST, DROP_SHADOW, GRAYSCALE, HUE_ROTATE, INVERT, OPACITY, SEPIA, SATURATE,
33+		ATTR, TYPE, ENV, IF,
34 	// Easing Functions
35 		EASING_FUNCTION, LINEAR_EASING_FUNCTION, LINEAR, EASE, EASE_IN, EASE_OUT, EASE_IN_OUT, CUBIC_BEZIER_FUNCTION, 
36 		STEP_START, STEP_END, STEPS_FUNCTION, JUMP_START, JUMP_END, JUMP_NONE, JUMP_BOTH, 
37@@ -97,7 +98,7 @@ enum class UnitType : short {
38 		MATRIX,	MATRIX3D, PERSPECTIVE, ROTATE, ROTATE3D, ROTATEX, ROTATEY, ROTATEZ, SCALE, SCALE3D, SCALEX, SCALEY, SCALEZ, TRANSLATE, TRANSLATE3D, TRANSLATEX, TRANSLATEY, TRANSLATEZ, 
39 		SKEW, SKEWX, SKEWY,
40 	// Rounding
41-		NEAREST, UP, DOWN, TO_ZERO,
42+		NEAREST, UP, DOWN, TO_ZERO,	
43 
44 	// Keyword
45 		PRINT, SCREEN, TOKEN, FUNC, GROUP, NO_SUPPORT, IMAGE, STRING
46@@ -278,6 +279,39 @@ enum class KeyType : short {
47 	Z_INDEX, ZOOM
48 };
49 
50+class IndexedMap {
51+	public:
52+		std::vector<std::pair<std::string, std::vector<Unit>>> map{};
53+		std::vector<Unit> find(std::string key) {
54+			for (size_t i = 0; i < map.size(); i++) {
55+				if (map[i].first == key) {
56+					return map[i].second;
57+				}
58+			}
59+		}
60+
61+		size_t index(std::string key) {
62+			for (size_t i = 0; i < map.size(); i++) {
63+				if (map[i].first == key) {
64+					return i;
65+				}
66+			}
67+		}
68+		std::vector<Unit> at(size_t i) {
69+			return map[i].second;
70+		}
71+
72+		size_t set(std::string key, std::vector<Unit> value) {
73+			for (size_t i = 0; i < map.size(); i++) {
74+				if (map[i].first == key) {
75+					map[i].second = value;
76+					return i;
77+				}
78+			}
79+			map.push_back({key, value});
80+			return map.size()-1;
81+		}
82+};
83 
84 class Style {
85 	public:
86@@ -287,7 +321,9 @@ class Style {
87 		std::vector<std::vector<std::string>> selector{};
88 		
89 		std::unordered_map<KeyType, std::vector<Unit>> properties{};
90-		std::unordered_map<std::string, std::vector<Unit>> variables{};
91+		
92+		IndexedMap variables{};
93+		std::vector<std::string> strings{};
94 
95 		// Nesting
96 		std::vector<Style> children{};
97diff --git a/include/parser.h b/include/parser.h
98index ba33470..f7b94c8 100755
99--- a/include/parser.h
100+++ b/include/parser.h
101@@ -20,6 +20,6 @@ struct ParsedDocument {
102 std::unordered_map<std::string, std::string> parseAttributes(std::string_view& token);
103 ParsedDocument parseDocument(std::istream& inputStream);
104 Style parseCSS(std::istream& inputStream);
105-std::vector<Unit> getUnit(std::string);
106+std::vector<Unit> getUnit(Style*, std::string);
107 
108 #endif
109diff --git a/playground/css_unit.cc b/playground/css_unit.cc
110index c064e68..640ae55 100644
111--- a/playground/css_unit.cc
112+++ b/playground/css_unit.cc
113@@ -4,7 +4,8 @@
114 #include <fstream>
115 
116 int main() {
117-	std::vector<Unit> test = getUnit("attr(size px)");
118+	Style style{};
119+	std::vector<Unit> test = getUnit(&style, "\"test\"");
120 
121 	std::cout << "Done" << std::endl;
122 }
123diff --git a/src/grim.cc b/src/grim.cc
124index 23940a2..556b914 100755
125--- a/src/grim.cc
126+++ b/src/grim.cc
127@@ -1313,7 +1313,6 @@ float UnitLengthValue(Node* n, const std::vector<Unit>& units, size_t start, siz
128 
129 				i += unit.value.INT;
130 				break;
131-			case UnitType::ATTR
132 
133 			// Need to add variable injection and group handling
134 		}
135diff --git a/src/parser.cc b/src/parser.cc
136index 78fa6a0..8b51153 100755
137--- a/src/parser.cc
138+++ b/src/parser.cc
139@@ -1019,6 +1019,11 @@ static const std::unordered_map<std::string_view, UnitType> kFunc{
140 	{"skewX", UnitType::SKEWX},
141 	{"skewY", UnitType::SKEWY},
142 	{"url", UnitType::URL},
143+	{"attr", UnitType::ATTR},
144+	{"type", UnitType::TYPE},
145+	{"env", UnitType::ENV},
146+	{"if", UnitType::IF},
147+	{"var", UnitType::VAR},
148 	{"", UnitType::GROUP}
149 };
150 
151@@ -1027,10 +1032,16 @@ static const std::unordered_map<std::string_view, float> kAbsSize{
152 	{"large",1.2f}, {"x-large",1.5f}, {"xx-large",2.0f}, {"xxx-large",3.0f}
153 };
154 
155-std::vector<Unit> getUnit(std::string value) {
156+/*
157+	Parses a string into Unit's and stores variables & strings into the Style object
158+
159+*/
160+
161+std::vector<Unit> getUnit(Style* s, std::string value) {
162 	std::vector<Unit> units;	
163 	
164 	std::string buffer = "";
165+	std::string str_buffer = "";
166 	int parenDepth = 0;
167 	bool inQuotes = false;
168 	// Needs to not be empty but can't be a quote
169@@ -1040,14 +1051,23 @@ std::vector<Unit> getUnit(std::string value) {
170 	for (size_t i = 0; i < value.length(); i++) {
171 		char v = value[i];
172 		if (v == '\\' && !escaped) escaped = true;
173-		if ((v == '"' || v == '\'') && parenDepth == 0) {
174+		if (!escaped && (v == '"' || v == '\'') && parenDepth == 0) {
175 			if (inQuotes && v == quoteType) {
176+				s->strings.push_back(str_buffer);
177+				str_buffer.clear();
178+
179+				Unit unit{};
180+				unit.type = UnitType::STRING;
181+				unit.isFunc = false;
182+				unit.value.INT = s->strings.size()-1;
183+				units.push_back(unit);
184+
185 				inQuotes = false;
186 			} else if (!inQuotes) {
187 				quoteType = v;
188 				inQuotes = true;
189 			}
190-
191+			continue;
192 		}
193 
194 		if (!inQuotes) {
195@@ -1076,7 +1096,7 @@ std::vector<Unit> getUnit(std::string value) {
196 				}
197 			}
198 
199-			std::vector<Unit> children = getUnit(value);
200+			std::vector<Unit> children = getUnit(s, value);
201 			
202 			Unit unit;
203 			unit.isFunc = true;
204@@ -1101,88 +1121,75 @@ std::vector<Unit> getUnit(std::string value) {
205 
206 			// Split by spaces into parts
207 
208-			bool found = false;
209 			if (auto it = kMatch.find(buffer); it != kMatch.end()) { 
210 				/*
211 					Keyword Matching
212 				*/
213 				unit.type = it->second;
214 				// the value is not used here
215-				found = true;
216 			} else if (auto it = kColors.find(buffer); it != kColors.end()) { 
217 				/*
218 					Color Matching
219 				*/
220 				unit.type = UnitType::HEX;
221 				unit.value.UINT = it->second;
222-				found = true;
223 			} else {
224+				bool found = false;
225 				for (const auto& [suffix, type, trim] : table) {
226 					if (buffer.ends_with(suffix)) {
227-						unit.value.FLOAT = std::stof(std::string(buffer.substr(0, buffer.size() - trim)));
228-						unit.type = type;
229 						found = true;
230+						try {
231+							unit.value.FLOAT = std::stof(std::string(buffer.substr(0, buffer.size() - trim)));
232+						} catch (...) {
233+							unit.value.FLOAT = 0.0f;
234+						}
235+
236+						unit.type = type;
237 						break;
238 					}
239 				}
240-			}
241 
242-			if (!found) {
243-				if (buffer.starts_with("#")) {
244-					/*
245-						# Prefix for HEX codes
246-					*/
247-					unit.type = UnitType::HEX;
248-					unit.value.UINT = std::stoul(buffer.substr(1), nullptr, 16);
249-					found = true;
250-				} else if (auto it = kAbsSize.find(buffer); it != kAbsSize.end()) { 
251-					/*
252-						Absolute size matching
253-					*/
254-					unit.type = UnitType::EM;
255-					unit.value.FLOAT = it->second;
256-					found = true;
257-				} else {
258-					// Maybe its a number?
259-					try {
260-						unit.value.FLOAT = std::stof(buffer);
261-						unit.type = UnitType::NUMBER;
262-						found = true;
263-					} catch (...) {
264-						found = false;
265+				if (!found) {
266+					if (buffer.starts_with("#") && buffer.length() > 1) {
267+						/*
268+							# Prefix for HEX codes
269+						*/
270+						unit.type = UnitType::HEX;
271+						unit.value.UINT = std::stoul(buffer.substr(1), nullptr, 16);
272+					} else if (auto it = kAbsSize.find(buffer); it != kAbsSize.end()) { 
273+						/*
274+							Absolute size matching
275+						*/
276+						unit.type = UnitType::EM;
277+						unit.value.FLOAT = it->second;
278+					} else {
279+						// Maybe its a number?
280+						try {
281+							unit.value.FLOAT = std::stof(buffer);
282+							unit.type = UnitType::NUMBER;
283+						} catch (...) {
284+							// If we are here it is not a known parsable word, this could be a typo 
285+							// or a keyword like with the attr(size px) function. Here px would be
286+							// parsed but not size.
287+							if (!buffer.empty() && buffer.find_first_not_of(' ') != std::string::npos) {
288+								unit.type = UnitType::VAR;
289+								unit.value.INT = s->variables.set(buffer, {});
290+							} else {
291+								continue;
292+							}
293+						}
294 					}
295 				}
296-				/*
297-					need to handle strings
298-				*/
299-			}
300-
301-			if (found) {
302-				// Only process if its found
303-				units.push_back(unit);
304-
305-				buffer.clear();
306-			} else if (v == ',') {
307-				// if we hit a comma before we match we can dump the
308-				// buffer and try again
309-				std::cerr << "Unable to parse buffer: " << buffer << std::endl;
310-				buffer.clear();
311 			}
312 
313+			units.push_back(unit);
314+			buffer.clear();
315 		} else if (inQuotes) {
316-			if (v == '"') continue;
317-			Unit u;
318-			u.isFunc = false;
319-			u.type = UnitType::STRING;
320-			UnitValue uv;
321-			uv.CHAR = v;
322-			u.value = uv;
323-
324-			units.push_back(u);
325+			str_buffer.push_back(v);
326 		} else {
327 			buffer.push_back(v);
328 		}
329-		
330+
331 		escaped = false;
332 		if (v == '\\') escaped = true;
333 	}
334@@ -1341,7 +1348,7 @@ Style parseCSS(std::istream& inputStream) {
335 				}
336 
337 				if (key.length() > 2 && key[0] == '-' && key[1] == '-') {
338-					current->variables[key] = getUnit(value);
339+					current->variables.set(key, getUnit(current, value));
340 				} else {
341 					KeyType keyENUM;
342 
343@@ -1350,7 +1357,7 @@ Style parseCSS(std::istream& inputStream) {
344 					} else {
345 						std::cout << "Invalid property name: " << key << std::endl;
346 					}
347-					current->properties[keyENUM] = getUnit(value); 
348+					current->properties[keyENUM] = getUnit(current, value); 
349 				}
350 			}
351 			buffer.clear();
352diff --git a/tests/css_unit.cc b/tests/css_unit.cc
353index 7a280b0..515fb90 100755
354--- a/tests/css_unit.cc
355+++ b/tests/css_unit.cc
356@@ -1,827 +1,131 @@
357 #include <catch_amalgamated.hpp>
358 #include "../include/grim.h"
359 #include "../include/parser.h"
360-#include <iostream>
361-#include <fstream>
362 
363-
364-TEST_CASE("getUnit can parse color values") {
365-	SECTION("getUnit can parse hex") {
366-		std::vector<Unit> test = getUnit("#ff7dff1a");
367-		INFO(test[0].value.UINT);
368-		REQUIRE(0xff7dff1a == test[0].value.UINT);
369-	};
370-
371-	SECTION("getUnit can parse rgba") {
372-		std::vector<Unit> test = getUnit("rgba(255 125 255 / 10%)");
373-		REQUIRE(test[0].type == UnitType::RGBA);
374-		REQUIRE(test[0].value.INT == 5);
375-		REQUIRE(test[1].type == UnitType::NUMBER);
376-		REQUIRE(test[1].value.FLOAT == 255.0f);
377-		REQUIRE(test[2].type == UnitType::NUMBER);
378-		REQUIRE(test[2].value.FLOAT == 125.0f);
379-		REQUIRE(test[3].type == UnitType::NUMBER);
380-		REQUIRE(test[3].value.FLOAT == 255.0f);
381-		REQUIRE(test[4].type == UnitType::DIV);
382-		REQUIRE(test[5].type == UnitType::PERCENT);
383-		REQUIRE(test[5].value.FLOAT == 10.0f);
384-	};
385-
386-	SECTION("getUnit can parse rgb") {
387-		std::vector<Unit> test = getUnit("rgb(255, 125, 255)");
388-		REQUIRE(test[0].type == UnitType::RGB);
389-		REQUIRE(test[0].value.INT == 3);
390-		REQUIRE(test[1].type == UnitType::NUMBER);
391-		REQUIRE(test[1].value.FLOAT == 255.0f);
392-		REQUIRE(test[2].type == UnitType::NUMBER);
393-		REQUIRE(test[2].value.FLOAT == 125.0f);
394-		REQUIRE(test[3].type == UnitType::NUMBER);
395-		REQUIRE(test[3].value.FLOAT == 255.0f);
396-	}
397-
398-	SECTION("getUnit can parse hsl") {
399-		std::vector<Unit> t = getUnit("hsl(300deg 100% 74.51%)");
400-		REQUIRE(t[0].type == UnitType::HSL);
401-		REQUIRE(t[0].value.INT == 3);
402-		REQUIRE(t[1].type == UnitType::DEG);
403-		REQUIRE(t[1].value.FLOAT == 300.0f);
404-		REQUIRE(t[2].type == UnitType::PERCENT);
405-		REQUIRE(t[2].value.FLOAT == 100.0f);
406-		REQUIRE(t[3].type == UnitType::PERCENT);
407-		REQUIRE(t[3].value.FLOAT == 74.51f);
408-
409-	}
410-
411-	SECTION("getUnit can parse hsla") {
412-		std::vector<Unit> t = getUnit("hsl(300deg 100% 74.51% / 10%)");
413-		REQUIRE(t[0].type == UnitType::HSL);
414-		REQUIRE(t[0].value.INT == 5);
415-		REQUIRE(t[1].type == UnitType::DEG);
416-		REQUIRE(t[1].value.FLOAT == 300.0f);
417-		REQUIRE(t[2].type == UnitType::PERCENT);
418-		REQUIRE(t[2].value.FLOAT == 100.0f);
419-		REQUIRE(t[3].type == UnitType::PERCENT);
420-		REQUIRE(t[3].value.FLOAT == 74.51f);
421-		REQUIRE(t[4].type == UnitType::DIV);
422-		REQUIRE(t[5].type == UnitType::PERCENT);
423-		REQUIRE(t[5].value.FLOAT == 10.0f);
424-	}
425-
426-	// px
427-	SECTION("getUnit can parse px") {
428-		std::vector<Unit> test = getUnit("10px 10.5px");
429-		REQUIRE(10.0f == test[0].value.FLOAT);
430-		REQUIRE(UnitType::PX == test[0].type);
431-		REQUIRE(10.5f == test[1].value.FLOAT);
432-		REQUIRE(UnitType::PX == test[1].type);
433-	}
434-
435-	// em
436-	SECTION("getUnit can parse em") {
437-		std::vector<Unit> test = getUnit("1.2em 0em");
438-		REQUIRE(1.2f == test[0].value.FLOAT);
439-		REQUIRE(UnitType::EM == test[0].type);
440-		REQUIRE(0.0f == test[1].value.FLOAT);
441-		REQUIRE(UnitType::EM == test[1].type);
442-	}
443-
444-	// %
445-	SECTION("getUnit can parse percent") {
446-		std::vector<Unit> test = getUnit("50% 100.5%");
447-		REQUIRE(50.0f == test[0].value.FLOAT);
448-		REQUIRE(UnitType::PERCENT == test[0].type);
449-		REQUIRE(100.5f == test[1].value.FLOAT);
450-		REQUIRE(UnitType::PERCENT == test[1].type);
451-	}
452-
453-	// cm
454-	SECTION("getUnit can parse cm") {
455-		std::vector<Unit> test = getUnit("2.54cm 0.5cm");
456-		REQUIRE(2.54f == test[0].value.FLOAT);
457-		REQUIRE(UnitType::CM == test[0].type);
458-		REQUIRE(0.5f == test[1].value.FLOAT);
459-		REQUIRE(UnitType::CM == test[1].type);
460-	}
461-
462-	// cap
463-	SECTION("getUnit can parse cap") {
464-		std::vector<Unit> test = getUnit("3cap 0cap");
465-		REQUIRE(3.0f == test[0].value.FLOAT);
466-		REQUIRE(UnitType::CAP == test[0].type);
467-		REQUIRE(0.0f == test[1].value.FLOAT);
468-		REQUIRE(UnitType::CAP == test[1].type);
469-	}
470-
471-	// ch
472-	SECTION("getUnit can parse ch") {
473-		std::vector<Unit> test = getUnit("10ch 0.5ch");
474-		REQUIRE(10.0f == test[0].value.FLOAT);
475-		REQUIRE(UnitType::CH == test[0].type);
476-		REQUIRE(0.5f == test[1].value.FLOAT);
477-		REQUIRE(UnitType::CH == test[1].type);
478-	}
479-
480-	// ex
481-	SECTION("getUnit can parse ex") {
482-		std::vector<Unit> test = getUnit("2ex 1.5ex");
483-		REQUIRE(2.0f == test[0].value.FLOAT);
484-		REQUIRE(UnitType::EX == test[0].type);
485-		REQUIRE(1.5f == test[1].value.FLOAT);
486-		REQUIRE(UnitType::EX == test[1].type);
487-	}
488-
489-	// ic
490-	SECTION("getUnit can parse ic") {
491-		std::vector<Unit> test = getUnit("5ic 0ic");
492-		REQUIRE(5.0f == test[0].value.FLOAT);
493-		REQUIRE(UnitType::IC == test[0].type);
494-		REQUIRE(0.0f == test[1].value.FLOAT);
495-		REQUIRE(UnitType::IC == test[1].type);
496-	}
497-
498-	// lh
499-	SECTION("getUnit can parse lh") {
500-		std::vector<Unit> test = getUnit("1.2lh 0lh");
501-		REQUIRE(1.2f == test[0].value.FLOAT);
502-		REQUIRE(UnitType::LH == test[0].type);
503-		REQUIRE(0.0f == test[1].value.FLOAT);
504-		REQUIRE(UnitType::LH == test[1].type);
505-	}
506-
507-	// rcap
508-	SECTION("getUnit can parse rcap") {
509-		std::vector<Unit> test = getUnit("2rcap 0.5rcap");
510-		REQUIRE(2.0f == test[0].value.FLOAT);
511-		REQUIRE(UnitType::RCAP == test[0].type);
512-		REQUIRE(0.5f == test[1].value.FLOAT);
513-		REQUIRE(UnitType::RCAP == test[1].type);
514-	}
515-
516-	// rch
517-	SECTION("getUnit can parse rch") {
518-		std::vector<Unit> test = getUnit("3rch 0rch");
519-		REQUIRE(3.0f == test[0].value.FLOAT);
520-		REQUIRE(UnitType::RCH == test[0].type);
521-		REQUIRE(0.0f == test[1].value.FLOAT);
522-		REQUIRE(UnitType::RCH == test[1].type);
523-	}
524-
525-	// rem
526-	SECTION("getUnit can parse rem") {
527-		std::vector<Unit> test = getUnit("1rem 0.5rem");
528-		REQUIRE(1.0f == test[0].value.FLOAT);
529-		REQUIRE(UnitType::REM == test[0].type);
530-		REQUIRE(0.5f == test[1].value.FLOAT);
531-		REQUIRE(UnitType::REM == test[1].type);
532-	}
533-
534-	// rex
535-	SECTION("getUnit can parse rex") {
536-		std::vector<Unit> test = getUnit("1.5rex 0rex");
537-		REQUIRE(1.5f == test[0].value.FLOAT);
538-		REQUIRE(UnitType::REX == test[0].type);
539-		REQUIRE(0.0f == test[1].value.FLOAT);
540-		REQUIRE(UnitType::REX == test[1].type);
541-	}
542-
543-	// ric
544-	SECTION("getUnit can parse ric") {
545-		std::vector<Unit> test = getUnit("2ric 0.25ric");
546-		REQUIRE(2.0f == test[0].value.FLOAT);
547-		REQUIRE(UnitType::RIC == test[0].type);
548-		REQUIRE(0.25f == test[1].value.FLOAT);
549-		REQUIRE(UnitType::RIC == test[1].type);
550-	}
551-
552-	// rlh
553-	SECTION("getUnit can parse rlh") {
554-		std::vector<Unit> test = getUnit("1.1rlh 0rlh");
555-		REQUIRE(1.1f == test[0].value.FLOAT);
556-		REQUIRE(UnitType::RLH == test[0].type);
557-		REQUIRE(0.0f == test[1].value.FLOAT);
558-		REQUIRE(UnitType::RLH == test[1].type);
559-	}
560-
561-	// vh
562-	SECTION("getUnit can parse vh") {
563-		std::vector<Unit> test = getUnit("50vh 100vh");
564-		REQUIRE(50.0f == test[0].value.FLOAT);
565-		REQUIRE(UnitType::VH == test[0].type);
566-		REQUIRE(100.0f == test[1].value.FLOAT);
567-		REQUIRE(UnitType::VH == test[1].type);
568-	}
569-
570-	// vw
571-	SECTION("getUnit can parse vw") {
572-		std::vector<Unit> test = getUnit("25vw 0vw");
573-		REQUIRE(25.0f == test[0].value.FLOAT);
574-		REQUIRE(UnitType::VW == test[0].type);
575-		REQUIRE(0.0f == test[1].value.FLOAT);
576-		REQUIRE(UnitType::VW == test[1].type);
577-	}
578-
579-	// vmax
580-	SECTION("getUnit can parse vmax") {
581-		std::vector<Unit> test = getUnit("75vmax 0vmax");
582-		REQUIRE(75.0f == test[0].value.FLOAT);
583-		REQUIRE(UnitType::VMAX == test[0].type);
584-		REQUIRE(0.0f == test[1].value.FLOAT);
585-		REQUIRE(UnitType::VMAX == test[1].type);
586-	}
587-
588-	// vmin
589-	SECTION("getUnit can parse vmin") {
590-		std::vector<Unit> test = getUnit("10vmin 99.9vmin");
591-		REQUIRE(10.0f == test[0].value.FLOAT);
592-		REQUIRE(UnitType::VMIN == test[0].type);
593-		REQUIRE(99.9f == test[1].value.FLOAT);
594-		REQUIRE(UnitType::VMIN == test[1].type);
595-	}
596-
597-	// vb
598-	SECTION("getUnit can parse vb") {
599-		std::vector<Unit> test = getUnit("20vb 0vb");
600-		REQUIRE(20.0f == test[0].value.FLOAT);
601-		REQUIRE(UnitType::VB == test[0].type);
602-		REQUIRE(0.0f == test[1].value.FLOAT);
603-		REQUIRE(UnitType::VB == test[1].type);
604-	}
605-
606-	// vi
607-	SECTION("getUnit can parse vi") {
608-		std::vector<Unit> test = getUnit("5vi 1vi");
609-		REQUIRE(5.0f == test[0].value.FLOAT);
610-		REQUIRE(UnitType::VI == test[0].type);
611-		REQUIRE(1.0f == test[1].value.FLOAT);
612-		REQUIRE(UnitType::VI == test[1].type);
613-	}
614-
615-	// cqw
616-	SECTION("getUnit can parse cqw") {
617-		std::vector<Unit> test = getUnit("30cqw 0cqw");
618-		REQUIRE(30.0f == test[0].value.FLOAT);
619-		REQUIRE(UnitType::CQW == test[0].type);
620-		REQUIRE(0.0f == test[1].value.FLOAT);
621-		REQUIRE(UnitType::CQW == test[1].type);
622-	}
623-
624-	// cqh
625-	SECTION("getUnit can parse cqh") {
626-		std::vector<Unit> test = getUnit("40cqh 10.5cqh");
627-		REQUIRE(40.0f == test[0].value.FLOAT);
628-		REQUIRE(UnitType::CQH == test[0].type);
629-		REQUIRE(10.5f == test[1].value.FLOAT);
630-		REQUIRE(UnitType::CQH == test[1].type);
631-	}
632-
633-	// cqi
634-	SECTION("getUnit can parse cqi") {
635-		std::vector<Unit> test = getUnit("15cqi 0cqi");
636-		REQUIRE(15.0f == test[0].value.FLOAT);
637-		REQUIRE(UnitType::CQI == test[0].type);
638-		REQUIRE(0.0f == test[1].value.FLOAT);
639-		REQUIRE(UnitType::CQI == test[1].type);
640-	}
641-
642-	// cqb
643-	SECTION("getUnit can parse cqb") {
644-		std::vector<Unit> test = getUnit("25cqb 1cqb");
645-		REQUIRE(25.0f == test[0].value.FLOAT);
646-		REQUIRE(UnitType::CQB == test[0].type);
647-		REQUIRE(1.0f == test[1].value.FLOAT);
648-		REQUIRE(UnitType::CQB == test[1].type);
649-	}
650-
651-	// cqmin
652-	SECTION("getUnit can parse cqmin") {
653-		std::vector<Unit> test = getUnit("10cqmin 0cqmin");
654-		REQUIRE(10.0f == test[0].value.FLOAT);
655-		REQUIRE(UnitType::CQMIN == test[0].type);
656-		REQUIRE(0.0f == test[1].value.FLOAT);
657-		REQUIRE(UnitType::CQMIN == test[1].type);
658-	}
659-
660-	// cqmax
661-	SECTION("getUnit can parse cqmax") {
662-		std::vector<Unit> test = getUnit("90cqmax \n 50.5cqmax");
663-		REQUIRE(90.0f == test[0].value.FLOAT);
664-		REQUIRE(UnitType::CQMAX == test[0].type);
665-		REQUIRE(50.5f == test[1].value.FLOAT);
666-		REQUIRE(UnitType::CQMAX == test[1].type);
667-	}
668-
669-	// mm
670-	SECTION("getUnit can parse mm") {
671-		std::vector<Unit> test = getUnit("10mm		 0.1mm");
672-		REQUIRE(10.0f == test[0].value.FLOAT);
673-		REQUIRE(UnitType::MM == test[0].type);
674-		REQUIRE(0.1f == test[1].value.FLOAT);
675-		REQUIRE(UnitType::MM == test[1].type);
676-	}
677-
678-	// q
679-	SECTION("getUnit can parse q") {
680-		std::vector<Unit> test = getUnit("40q,          1q");
681-		REQUIRE(40.0f == test[0].value.FLOAT);
682-		REQUIRE(UnitType::Q == test[0].type);
683-		REQUIRE(1.0f == test[1].value.FLOAT);
684-		REQUIRE(UnitType::Q == test[1].type);
685-	}
686-
687-	// in
688-	SECTION("getUnit can parse in") {
689-		std::vector<Unit> test = getUnit("1in          0.5in");
690-		REQUIRE(1.0f == test[0].value.FLOAT);
691-		REQUIRE(UnitType::IN == test[0].type);
692-		REQUIRE(0.5f == test[1].value.FLOAT);
693-		REQUIRE(UnitType::IN == test[1].type);
694-	}
695-
696-	// pc
697-	SECTION("getUnit can parse pc") {
698-		std::vector<Unit> test = getUnit("6pc, 0pc");
699-		REQUIRE(6.0f == test[0].value.FLOAT);
700-		REQUIRE(UnitType::PC == test[0].type);
701-		REQUIRE(0.0f == test[1].value.FLOAT);
702-		REQUIRE(UnitType::PC == test[1].type);
703-	}
704-
705-	// pt
706-	SECTION("getUnit can parse pt") {
707-		std::vector<Unit> test = getUnit("12pt");
708-		REQUIRE(12.0f == test[0].value.FLOAT);
709-		REQUIRE(UnitType::PT == test[0].type);
710-	}
711-
712-	// HEX Color
713-	SECTION("getUnit can parse a hex color") {
714-		std::vector<Unit> test = getUnit("#000000");
715-		REQUIRE(0x000000 == test[0].value.UINT);
716-		REQUIRE(UnitType::HEX == test[0].type);
717-	}
718-
719-	// xx-small abs unit
720-	SECTION("getUnit can parse a xx-small abs unit") {
721-		std::vector<Unit> test = getUnit("xx-small");
722-		REQUIRE(0.6f == test[0].value.FLOAT);
723-		REQUIRE(UnitType::EM == test[0].type);
724-	}
725-
726-	// x-small abs unit
727-	SECTION("getUnit can parse an x-small abs unit") {
728-		std::vector<Unit> test = getUnit("x-small");
729-		REQUIRE(0.75f == test[0].value.FLOAT);
730-		REQUIRE(UnitType::EM == test[0].type);
731-	}
732-
733-	// small abs unit
734-	SECTION("getUnit can parse a small abs unit") {
735-		std::vector<Unit> test = getUnit("small");
736-		REQUIRE(0.89f == test[0].value.FLOAT);
737-		REQUIRE(UnitType::EM == test[0].type);
738-	}
739-
740-	// medium abs unit
741-	SECTION("getUnit can parse a medium abs unit") {
742-		std::vector<Unit> test = getUnit("medium");
743-		REQUIRE(1.0f == test[0].value.FLOAT);
744-		REQUIRE(UnitType::EM == test[0].type);
745-	}
746-
747-	// large abs unit
748-	SECTION("getUnit can parse a large abs unit") {
749-		std::vector<Unit> test = getUnit("large");
750-		REQUIRE(1.2f == test[0].value.FLOAT);
751-		REQUIRE(UnitType::EM == test[0].type);
752-	}
753-
754-	// x-large abs unit
755-	SECTION("getUnit can parse an x-large abs unit") {
756-		std::vector<Unit> test = getUnit("x-large");
757-		REQUIRE(1.5f == test[0].value.FLOAT);
758-		REQUIRE(UnitType::EM == test[0].type);
759-	}
760-
761-	// xx-large abs unit
762-	SECTION("getUnit can parse an xx-large abs unit") {
763-		std::vector<Unit> test = getUnit("xx-large");
764-		REQUIRE(2.0f == test[0].value.FLOAT);
765-		REQUIRE(UnitType::EM == test[0].type);
766-	}
767-
768-	// xxx-large abs unit
769-	SECTION("getUnit can parse an xxx-large abs unit") {
770-		std::vector<Unit> test = getUnit("xxx-large");
771-		REQUIRE(3.0f == test[0].value.FLOAT);
772-		REQUIRE(UnitType::EM == test[0].type);
773-	}
774-
775-	// small and large abs unit
776-	SECTION("getUnit can parse two abs units with a space") {
777-		std::vector<Unit> test = getUnit("small large");
778-		REQUIRE(0.89f == test[0].value.FLOAT);
779-		REQUIRE(1.2f == test[1].value.FLOAT);
780-		REQUIRE(UnitType::EM == test[0].type);
781-		REQUIRE(UnitType::EM == test[1].type);
782-	}
783-
784-	// small and large abs unit
785-	SECTION("getUnit can parse two abs units with a comma") {
786-		std::vector<Unit> test = getUnit("small, large");
787-		REQUIRE(0.89f == test[0].value.FLOAT);
788-		REQUIRE(1.2f == test[1].value.FLOAT);
789-		REQUIRE(UnitType::EM == test[0].type);
790-		REQUIRE(UnitType::EM == test[1].type);
791-	}
792-
793-	// baseline
794-	SECTION("getUnit can parse baseline into first baseline") {
795-		std::vector<Unit> test = getUnit("baseline");
796-		REQUIRE(UnitType::FIRST_BASELINE == test[0].type);
797-	}
798-
799-	// first baseline
800-	SECTION("getUnit can parse first baseline") {
801-		std::vector<Unit> test = getUnit("first baseline");
802-		REQUIRE(UnitType::FIRST_BASELINE == test[0].type);
803-	}
804-
805-	// last baseline
806-	SECTION("getUnit can parse last baseline") {
807-		std::vector<Unit> test = getUnit("last baseline");
808-		REQUIRE(UnitType::LAST_BASELINE == test[0].type);
809-	}
810-
811-	// last baseline with another space seperated value
812-	SECTION("getUnit can parse last baseline with a space seperated value") {
813-		std::vector<Unit> test = getUnit("last baseline 10px");
814-		REQUIRE(UnitType::LAST_BASELINE == test[0].type);
815-		REQUIRE(10.0f == test[1].value.FLOAT);
816-		REQUIRE(UnitType::PX == test[1].type);
817-	}
818-
819-	// content-box
820-	SECTION("getUnit can parse content-box") {
821-		std::vector<Unit> test = getUnit("content-box");
822-		REQUIRE(UnitType::CONTENT == test[0].type);
823-	}
824-
825-	// padding-box
826-	SECTION("getUnit can parse padding-box") {
827-		std::vector<Unit> test = getUnit("padding-box");
828-		REQUIRE(UnitType::PADDING == test[0].type);
829-	}
830-
831-	// border-box
832-	SECTION("getUnit can parse border-box") {
833-		std::vector<Unit> test = getUnit("border-box");
834-		REQUIRE(UnitType::BORDER == test[0].type);
835-	}
836-
837-	// margin-box
838-	SECTION("getUnit can parse margin-box") {
839-		std::vector<Unit> test = getUnit("margin-box");
840-		REQUIRE(UnitType::MARGIN == test[0].type);
841-	}
842-
843-	// fill-box
844-	SECTION("getUnit can parse fill-box") {
845-		std::vector<Unit> test = getUnit("fill-box");
846-		REQUIRE(UnitType::FILL == test[0].type);
847-	}
848-
849-	// stroke-box
850-	SECTION("getUnit can parse stroke-box") {
851-		std::vector<Unit> test = getUnit("stroke-box");
852-		REQUIRE(UnitType::STROKE == test[0].type);
853-	}
854-
855-	// view-box
856-	SECTION("getUnit can parse view-box") {
857-		std::vector<Unit> test = getUnit("view-box");
858-		REQUIRE(UnitType::VIEW == test[0].type);
859-	}
860-
861-	// calc
862-	SECTION("getUnit can parse calc") {
863-		std::vector<Unit> test = getUnit("calc(10px)");
864-		REQUIRE(UnitType::CALC == test[0].type);
865-		REQUIRE(1 == test[0].value.INT);
866-
867-		REQUIRE(10.0f == test[1].value.FLOAT);
868-		REQUIRE(UnitType::PX == test[1].type);
869-	}
870-
871-	SECTION("getUnit can parse calc with add") {
872-		std::vector<Unit> test = getUnit("calc(10px + 14%)");
873-		REQUIRE(UnitType::CALC == test[0].type);
874-		REQUIRE(3 == test[0].value.INT);
875-
876-		REQUIRE(10.0f == test[1].value.FLOAT);
877-		REQUIRE(UnitType::PX == test[1].type);
878-
879-		REQUIRE(UnitType::ADD == test[2].type);
880-
881-		REQUIRE(14.0f == test[3].value.FLOAT);
882-		REQUIRE(UnitType::PERCENT == test[3].type);
883-	}
884-
885-
886-	// ---------- 1.  Whitespace handling ----------
887-	SECTION("calc ignores leading / trailing spaces and tabs") {
888-		std::vector<Unit> t = getUnit("  calc(  50vmin  )  ");
889-		REQUIRE(t[0].type == UnitType::CALC);
890-		REQUIRE(t[0].value.INT == 1);
891-		REQUIRE(t[1].value.FLOAT == 50.0f);
892-		REQUIRE(t[1].type == UnitType::VMIN);
893-	}
894-
895-	// ---------- 2.  Subtraction ----------
896-	SECTION("calc with subtraction") {
897-		std::vector<Unit> t = getUnit("calc(100% - 2em)");
898-		REQUIRE(t[0].type == UnitType::CALC);
899-		REQUIRE(t[2].type == UnitType::SUB);
900-		REQUIRE(t[3].value.FLOAT == 2.0f);
901-		REQUIRE(t[3].type == UnitType::EM);
902-	}
903-
904-	// ---------- 3.  Multiplication ----------
905-	SECTION("calc with multiply") {
906-		std::vector<Unit> t = getUnit("calc(3 * 4.5rem)");
907-		REQUIRE(t[2].type == UnitType::MULT);
908-		REQUIRE(t[3].value.FLOAT == 4.5f);
909-		REQUIRE(t[3].type == UnitType::REM);
910-	}
911-
912-	// ---------- 4.  Division ----------
913-	SECTION("calc with divide") {
914-		std::vector<Unit> t = getUnit("calc(90deg / 3)");
915-		REQUIRE(t[2].type == UnitType::DIV);
916-		REQUIRE(t[3].value.FLOAT == 3.0f);
917-		REQUIRE(t[1].type == UnitType::DEG);
918-	}
919-
920-	// ---------- 5.  Chained operators ----------
921-	SECTION("calc with three terms and two ops") {
922-		std::vector<Unit> t = getUnit("calc(10px + 20px - 5px)");
923-		REQUIRE(t[0].value.INT == 5); // px  +  px  -  px
924-		REQUIRE(t[2].type == UnitType::ADD);
925-		REQUIRE(t[4].type == UnitType::SUB);
926-	}
927-
928-	// ---------- 6.  Parentheses ----------
929-	SECTION("calc nested parentheses") {
930-		std::vector<Unit> t = getUnit("calc((2 * 3em) + 4px)");
931-		// The first child should be the subtree for the parens
932-		REQUIRE(t[0].type == UnitType::CALC);
933-		REQUIRE(t[0].value.INT == 6);
934-		REQUIRE(t[0].type == UnitType::CALC);
935-		REQUIRE(t[1].value.INT == 3);
936-		REQUIRE(t[6].type == UnitType::PX);
937-	}
938-
939-	// ---------- 7.  Constants ----------
940-	SECTION("calc with pi") {
941-		std::vector<Unit> t = getUnit("calc(pi * 30px)");
942-		REQUIRE(t[1].type == UnitType::PI);
943-		REQUIRE(t[2].type == UnitType::MULT);
944-		REQUIRE(t[3].value.FLOAT == 30.0f);
945-	}
946-
947-	// ---------- 8.  Negative numbers ----------
948-	SECTION("calc with negative value") {
949-		std::vector<Unit> t = getUnit("calc(-15vw + 10vw)");
950-		REQUIRE(t[1].value.FLOAT == -15.0f);
951-		REQUIRE(t[1].type == UnitType::VW);
952-	}
953-
954-	// ---------- 9.  Zero unit ----------
955-	SECTION("calc with zero px") {
956-		std::vector<Unit> t = getUnit("calc(0px + 5px)");
957-		REQUIRE(t[1].value.FLOAT == 0.0f);
958-		REQUIRE(t[1].type == UnitType::PX);
959-	}
960-
961-	// ---------- 10.  Scientific notation ----------
962-	SECTION("calc with scientific notation") {
963-		std::vector<Unit> t = getUnit("calc(1.2e3px)");
964-		REQUIRE(t[1].value.FLOAT == 1200.0f);
965-		REQUIRE(t[1].type == UnitType::PX);
966-	}
967-
968-	// ---------- 11.  Many spaces around operator ----------
969-	SECTION("calc with huge whitespace gap") {
970-		std::vector<Unit> t = getUnit("calc(50px     *     2)");
971-		REQUIRE(t[2].type == UnitType::MULT);
972-	}
973-
974-	// ---------- 12.  Double negation ----------
975-	SECTION("calc with double negation") {
976-		std::vector<Unit> t = getUnit("calc(10px - -5px)");
977-		REQUIRE(t[3].value.FLOAT == -5.0f);
978-		REQUIRE(t[2].type == UnitType::SUB);
979-	}
980-
981-	// ---------- 13.  Mixed units ----------
982-	SECTION("calc mixed vw and px") {
983-		std::vector<Unit> t = getUnit("calc(100vw - 20px)");
984-		REQUIRE(t[1].type == UnitType::VW);
985-		REQUIRE(t[3].type == UnitType::PX);
986-	}
987-
988-	// ---------- 14.  Functions inside calc ----------
989-	SECTION("calc with nested function") {
990-		std::vector<Unit> t = getUnit("calc(min(10px, 20px) + 5px)");
991-		// first child should be the min() subtree
992-		REQUIRE(t[1].type == UnitType::MIN);
993-		REQUIRE(t[5].value.FLOAT == 5.0f);
994-	}
995-
996-	SECTION("calc with infinity") {
997-		std::vector<Unit> t = getUnit("calc(infinity)");
998-		REQUIRE(t[1].type == UnitType::INF);
999-	}
1000-
1001-	SECTION("calc with negative infinity") {
1002-		std::vector<Unit> t = getUnit("calc(-infinity)");
1003-		REQUIRE(t[1].type == UnitType::NEGINF);
1004-		t = getUnit("calc(1 - -infinity)");
1005-		REQUIRE(t[1].type == UnitType::NUMBER);
1006-		REQUIRE(t[2].type == UnitType::SUB);
1007-		REQUIRE(t[3].type == UnitType::NEGINF);
1008-	}
1009-
1010-	SECTION("calc with NaN") {
1011-		std::vector<Unit> t = getUnit("calc(NaN)");
1012-		REQUIRE(t[1].type == UnitType::NaN);
1013-	}
1014-	
1015-	SECTION("calc with E") {
1016-		std::vector<Unit> t = getUnit("calc(e)");
1017-		REQUIRE(t[1].type == UnitType::E);
1018-	}
1019-
1020-	SECTION("content-distribution space-between") {
1021-		std::vector<Unit> t = getUnit("space-between");
1022-		REQUIRE(t[0].type == UnitType::BETWEEN);
1023-	}
1024-
1025-	SECTION("content-distribution space-around") {
1026-		std::vector<Unit> t = getUnit("space-around");
1027-		REQUIRE(t[0].type == UnitType::AROUND);
1028-	}
1029-	SECTION("content-distribution space-between") {
1030-		std::vector<Unit> t = getUnit("space-evenly");
1031-		REQUIRE(t[0].type == UnitType::EVENLY);
1032-	}
1033-	SECTION("content-distribution stretch") {
1034-		std::vector<Unit> t = getUnit("stretch");
1035-		REQUIRE(t[0].type == UnitType::STRETCH);
1036-	}
1037-	SECTION("content-position center") {
1038-		std::vector<Unit> t = getUnit("center");
1039-		REQUIRE(t[0].type == UnitType::CENTER);
1040-	}
1041-	SECTION("content-position start") {
1042-		std::vector<Unit> t = getUnit("start");
1043-		REQUIRE(t[0].type == UnitType::START);
1044-	}
1045-	SECTION("content-position end") {
1046-		std::vector<Unit> t = getUnit("end");
1047-		REQUIRE(t[0].type == UnitType::END);
1048-	}
1049-	SECTION("content-position flex-start") {
1050-		std::vector<Unit> t = getUnit("flex-start");
1051-		REQUIRE(t[0].type == UnitType::FLEX_START);
1052-	}
1053-	SECTION("content-position flex-end") {
1054-		std::vector<Unit> t = getUnit("flex-end");
1055-		REQUIRE(t[0].type == UnitType::FLEX_END);
1056-	}
1057-	SECTION("display-box contents") {
1058-		std::vector<Unit> t = getUnit("contents");
1059-		REQUIRE(t[0].type == UnitType::CONTENTS);
1060-	}
1061-
1062-	SECTION("display-box none") {
1063-		std::vector<Unit> t = getUnit("none");
1064-		REQUIRE(t[0].type == UnitType::NONE);
1065-	}
1066-	SECTION("display-inside flow") {
1067-		std::vector<Unit> t = getUnit("flow");
1068-		REQUIRE(t[0].type == UnitType::FLOW);
1069-	}
1070-	SECTION("display-inside flow-root") {
1071-		std::vector<Unit> t = getUnit("flow-root");
1072-		REQUIRE(t[0].type == UnitType::FLOW_ROOT);
1073-	}
1074-	SECTION("display-inside table") {
1075-		std::vector<Unit> t = getUnit("table");
1076-		REQUIRE(t[0].type == UnitType::TABLE);
1077-	}
1078-	SECTION("display-inside flex") {
1079-		std::vector<Unit> t = getUnit("flex");
1080-		REQUIRE(t[0].type == UnitType::FLEX);
1081-	}
1082-	SECTION("display-inside grid") {
1083-		std::vector<Unit> t = getUnit("grid");
1084-		REQUIRE(t[0].type == UnitType::GRID);
1085-	}
1086-	SECTION("display-inside ruby") {
1087-		std::vector<Unit> t = getUnit("ruby");
1088-		REQUIRE(t[0].type == UnitType::RUBY);
1089-	}
1090-	SECTION("display-internal table-row-group") {
1091-		std::vector<Unit> t = getUnit("table-row-group");
1092-		REQUIRE(t[0].type == UnitType::TABLE_ROW_GROUP);
1093-	}
1094-	SECTION("display-internal table-header-group") {
1095-		std::vector<Unit> t = getUnit("table-header-group");
1096-		REQUIRE(t[0].type == UnitType::TABLE_HEADER_GROUP);
1097-	}
1098-	SECTION("display-internal table-footer-group") {
1099-		std::vector<Unit> t = getUnit("table-footer-group");
1100-		REQUIRE(t[0].type == UnitType::TABLE_FOOTER_GROUP);
1101-	}
1102-	SECTION("display-internal table-column-group") {
1103-		std::vector<Unit> t = getUnit("table-column-group");
1104-		REQUIRE(t[0].type == UnitType::TABLE_COLUMN_GROUP);
1105-	}
1106-	SECTION("display-internal table-row") {
1107-		std::vector<Unit> t = getUnit("table-row");
1108-		REQUIRE(t[0].type == UnitType::TABLE_ROW);
1109-	}
1110-	SECTION("display-internal table-cell") {
1111-		std::vector<Unit> t = getUnit("table-cell");
1112-		REQUIRE(t[0].type == UnitType::TABLE_CELL);
1113-	}
1114-	SECTION("display-internal table-column") {
1115-		std::vector<Unit> t = getUnit("table-column");
1116-		REQUIRE(t[0].type == UnitType::TABLE_COLUMN);
1117-	}
1118-	SECTION("display-internal table-caption") {
1119-		std::vector<Unit> t = getUnit("table-caption");
1120-		REQUIRE(t[0].type == UnitType::TABLE_CAPTION);
1121-	}
1122-	SECTION("display-internal ruby-base") {
1123-		std::vector<Unit> t = getUnit("ruby-base");
1124-		REQUIRE(t[0].type == UnitType::RUBY_BASE);
1125-	}
1126-	SECTION("display-internal ruby-text") {
1127-		std::vector<Unit> t = getUnit("ruby-text");
1128-		REQUIRE(t[0].type == UnitType::RUBY_TEXT);
1129-	}
1130-	SECTION("display-internal ruby-base-container") {
1131-		std::vector<Unit> t = getUnit("ruby-base-container");
1132-		REQUIRE(t[0].type == UnitType::RUBY_BASE_CONTAINER);
1133-	}
1134-	SECTION("display-internal ruby-text-container") {
1135-		std::vector<Unit> t = getUnit("ruby-text-container");
1136-		REQUIRE(t[0].type == UnitType::RUBY_TEXT_CONTAINER);
1137-	}
1138-	SECTION("display-legacy inline-block") {
1139-		std::vector<Unit> t = getUnit("inline-block");
1140-		REQUIRE(t[0].type == UnitType::INLINE_BLOCK);
1141-	}
1142-	SECTION("display-legacy inline-table") {
1143-		std::vector<Unit> t = getUnit("inline-table");
1144-		REQUIRE(t[0].type == UnitType::INLINE_TABLE);
1145-	}
1146-	SECTION("display-legacy inline-flex") {
1147-		std::vector<Unit> t = getUnit("inline-flex");
1148-		REQUIRE(t[0].type == UnitType::INLINE_FLEX);
1149-	}
1150-	SECTION("display-legacy inline-grid") {
1151-		std::vector<Unit> t = getUnit("inline-grid");
1152-		REQUIRE(t[0].type == UnitType::INLINE_GRID);
1153-	}
1154-	SECTION("display-listitem list-item") {
1155-		std::vector<Unit> t = getUnit("list-item");
1156-		REQUIRE(t[0].type == UnitType::LISTITEM);
1157-	}
1158-	SECTION("display-outside block") {
1159-		std::vector<Unit> t = getUnit("block");
1160-		REQUIRE(t[0].type == UnitType::BLOCK);
1161-	}
1162-	SECTION("display-outside inline") {
1163-		std::vector<Unit> t = getUnit("inline");
1164-		REQUIRE(t[0].type == UnitType::INLINE);
1165-	}
1166-	SECTION("display-outside run-in") {
1167-		std::vector<Unit> t = getUnit("run-in");
1168-		REQUIRE(t[0].type == UnitType::RUN_IN);
1169-	}
1170+TEST_CASE("Comprehensive getUnit and Style State Tests") {
1171+    Style s;
1172+
1173+    SECTION("1. Color Spaces and Numerical Conversions") {
1174+        // Hex with Alpha
1175+        auto hex = getUnit(&s, "#ff7dff1a");
1176+        REQUIRE(hex[0].value.UINT == 0xff7dff1a);
1177+        REQUIRE(hex[0].type == UnitType::HEX);
1178+
1179+        // Functional RGB/RGBA
1180+        auto rgba = getUnit(&s, "rgba(255 125 255 / 10%)");
1181+        REQUIRE(rgba[0].type == UnitType::RGBA);
1182+        REQUIRE(rgba[1].value.FLOAT == 255.0f);
1183+        REQUIRE(rgba[4].type == UnitType::DIV);
1184+        REQUIRE(rgba[5].type == UnitType::PERCENT);
1185+        REQUIRE(rgba[5].value.FLOAT == 10.0f);
1186+
1187+        // HSL/HSLA
1188+        auto hsl = getUnit(&s, "hsl(300deg 100% 74.51% / 10%)");
1189+        REQUIRE(hsl[0].type == UnitType::HSL);
1190+        REQUIRE(hsl[1].type == UnitType::DEG);
1191+        REQUIRE(hsl[1].value.FLOAT == 300.0f);
1192+        REQUIRE(hsl[3].value.FLOAT == 74.51f);
1193+    }
1194+
1195+    SECTION("2. Full Unit Table Coverage") {
1196+        // Physical and Typographic Units
1197+        auto units = getUnit(&s, "10px 1.2em 50% 2.54cm 3cap 10ch 2ex 5ic 1.2lh 1rem 50vh 25vw 30cqw 10mm 1in 12pt 6pc 40q");
1198+        
1199+        std::vector<UnitType> expected = {
1200+            UnitType::PX, UnitType::EM, UnitType::PERCENT, UnitType::CM, UnitType::CAP, 
1201+            UnitType::CH, UnitType::EX, UnitType::IC, UnitType::LH, UnitType::REM, 
1202+            UnitType::VH, UnitType::VW, UnitType::CQW, UnitType::MM, UnitType::IN, 
1203+            UnitType::PT, UnitType::PC, UnitType::Q
1204+        };
1205+
1206+        for (size_t i = 0; i < expected.size(); i++) {
1207+            INFO("Testing unit at index " << i);
1208+            REQUIRE(units[i].type == expected[i]);
1209+        }
1210+    }
1211+
1212+    SECTION("3. Logical Keywords and Absolute Sizes") {
1213+        // Absolute Sizes (Matched via kAbsSize map)
1214+        auto sizes = getUnit(&s, "xx-small small medium xxx-large");
1215+        REQUIRE(sizes[0].value.FLOAT == 0.6f);
1216+        REQUIRE(sizes[1].value.FLOAT == 0.89f);
1217+        REQUIRE(sizes[2].value.FLOAT == 1.0f);
1218+        REQUIRE(sizes[3].value.FLOAT == 3.0f);
1219+
1220+        // Layout Keywords (Matched via kMatch map)
1221+        REQUIRE(getUnit(&s, "baseline")[0].type == UnitType::FIRST_BASELINE);
1222+        REQUIRE(getUnit(&s, "space-between")[0].type == UnitType::BETWEEN);
1223+        REQUIRE(getUnit(&s, "flex-start")[0].type == UnitType::FLEX_START);
1224+        REQUIRE(getUnit(&s, "border-box")[0].type == UnitType::BORDER);
1225+        REQUIRE(getUnit(&s, "none")[0].type == UnitType::NONE);
1226+    }
1227+
1228+    SECTION("4. Advanced Function Parsing (Calc & Nesting)") {
1229+        // Nested Math
1230+        auto t = getUnit(&s, "calc((10px + 5px) * 2)");
1231+        REQUIRE(t[0].type == UnitType::CALC);
1232+        // The parser handles parens by recursive calls to getUnit
1233+        // Verification depends on your kFunc and Unit structure
1234+        
1235+        // Constants and Scientific Notation
1236+        auto math = getUnit(&s, "calc(pi * 1.2e3px - infinity)");
1237+        REQUIRE(math[1].type == UnitType::PI);
1238+        REQUIRE(math[2].type == UnitType::MULT);
1239+        REQUIRE(math[3].value.FLOAT == 1200.0f);
1240+        REQUIRE(math[5].type == UnitType::INF);
1241+    }
1242+
1243+    SECTION("5. String Handling and Escape Logic") {
1244+        // Quoted strings
1245+        auto strTest = getUnit(&s, "\"Comic Sans\" 'Single Quote'");
1246+        REQUIRE(strTest[0].type == UnitType::STRING);
1247+        REQUIRE(s.strings[strTest[0].value.INT] == "Comic Sans");
1248+        REQUIRE(s.strings[strTest[1].value.INT] == "Single Quote");
1249+
1250+        // Escaped Characters (Verifying the escaped boolean logic)
1251+        // Note: Your parser uses 'escaped' for quotes and special chars
1252+        auto escaped = getUnit(&s, "\"String with \\\"quote\\\" inside\"");
1253+        REQUIRE(s.strings.back() == "String with \\\"quote\\\" inside");
1254+    }
1255+
1256+    SECTION("6. IndexedMap Variable Integration") {
1257+        // When a word isn't recognized, it becomes a VAR and is stored in s->variables
1258+        auto var1 = getUnit(&s, "my-variable");
1259+        REQUIRE(var1[0].type == UnitType::VAR);
1260+        size_t idx = var1[0].value.INT;
1261+        REQUIRE(s.variables.map[idx].first == "my-variable");
1262+
1263+        // Set the same variable again, ensure it returns the same index (via s->variables.set logic)
1264+        auto var2 = getUnit(&s, "my-variable");
1265+        REQUIRE(var2[0].value.INT == idx);
1266+        REQUIRE(s.variables.map.size() == 1); // Should not have duplicated
1267+    }
1268+
1269+    SECTION("7. Whitespace and Delimiter Robustness") {
1270+        // Mixed delimiters: tabs, multiple spaces, commas, newlines
1271+        auto multi = getUnit(&s, "10px,    20px\t\n30px");
1272+        REQUIRE(multi.size() == 3);
1273+        REQUIRE(multi[0].value.FLOAT == 10.0f);
1274+        REQUIRE(multi[1].value.FLOAT == 20.0f);
1275+        REQUIRE(multi[2].value.FLOAT == 30.0f);
1276+        
1277+        // Empty/Edge cases
1278+        auto empty = getUnit(&s, "   ");
1279+        REQUIRE(empty.empty());
1280+    }
1281+
1282+    SECTION("8. Display and Internal Table Keywords") {
1283+        // Comprehensive check of the display-inside/internal/legacy units
1284+        std::vector<std::pair<std::string, UnitType>> displayTests = {
1285+            {"flow-root", UnitType::FLOW_ROOT},
1286+            {"inline-flex", UnitType::INLINE_FLEX},
1287+            {"table-caption", UnitType::TABLE_CAPTION},
1288+            {"ruby-text-container", UnitType::RUBY_TEXT_CONTAINER},
1289+            {"run-in", UnitType::RUN_IN}
1290+        };
1291+
1292+        for (const auto& [str, type] : displayTests) {
1293+            REQUIRE(getUnit(&s, str)[0].type == type);
1294+        }
1295+    }
1296 }
1297-
1298-/*
1299-TEST_CASE("BENCHMARKS") {
1300-BENCHMARK("number") {
1301-	std::vector<Unit> t = getUnit("10");
1302-//	std::cout << sizeof(t) << std::endl;
1303-	std::cout << sizeof(t[0].type) << std::endl;
1304-};
1305-BENCHMARK("calc") {
1306-	std::vector<Unit> t = getUnit("calc(10 + 100%)");
1307-//	std::cout << sizeof(t) << std::endl;
1308-};
1309-}*/