home readme diff tree note docs

0commit b069ddad16a3806906845a747d32553385ccf6c1
1Author: Mason Wright <mason@lakefox.net>
2Date:   Mon Sep 1 13:33:59 2025 -0600
3
4    Working on a method for compiling CSS
5
6diff --git a/Makefile b/Makefile
7index d564b5d..b766151 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -2,7 +2,7 @@
11 CCFLAGS = -Wall -Wextra -std=c++2b -g
12 CC = clang++
13 
14-.PHONY: all clean run docs serve
15+.PHONY: all clean docs serve all_tests
16 
17 all: main
18 
19@@ -22,6 +22,12 @@ build/parser.o: src/parser.cc include/parser.h | build
20 
21 # --- Tests ---
22 
23+all_tests: build/html_node_test build/css_selector_test build/html_parser_test build/query_select_test
24+	build/html_node_test --skip-benchmarks
25+	build/css_selector_test --skip-benchmarks
26+	build/html_parser_test --skip-benchmarks
27+	build/query_select_test --skip-benchmarks
28+
29 build/html_node_test: tests/html_node.cc build/grim.o build/catch.o build/parser.o | build
30 	${CC} ${CCFLAGS} -Iinclude/ tests/html_node.cc build/grim.o build/catch.o build/parser.o -o build/html_node_test 
31 
32@@ -34,6 +40,9 @@ build/html_parser_test: tests/html_parser.cc build/grim.o build/parser.o build/c
33 build/css_parser_test: tests/css_parser.cc build/grim.o build/parser.o build/catch.o | build
34 	${CC} ${CCFLAGS} -Iinclude/ tests/css_parser.cc build/grim.o build/parser.o build/catch.o -o build/css_parser_test
35 
36+build/query_select_test: tests/query_select.cc build/grim.o build/parser.o build/catch.o | build
37+	${CC} ${CCFLAGS} -Iinclude/ tests/query_select.cc build/grim.o build/parser.o build/catch.o -o build/query_select_test
38+
39 build/catch.o: ./include/catch_amalgamated.cpp ./include/catch_amalgamated.hpp | build
40 	${CC} ${CCFLAGS} -Iinclude/ -c include/catch_amalgamated.cpp -o build/catch.o
41 
42@@ -47,9 +56,6 @@ build/catch.o: ./include/catch_amalgamated.cpp ./include/catch_amalgamated.hpp |
43 clean:
44 	rm -f main build/*.o
45 
46-run:
47-	clear && ./main
48-
49 MD_FILES := $(shell find docs/content -name "*.md")
50 HTML_FILES := $(MD_FILES:docs/content/%.md=docs/dist/%.html)
51 
52diff --git a/docs/content/features/supported-css-selectors.md b/docs/content/features/supported-css-selectors.md
53index 4dc2a6b..9f8886d 100755
54--- a/docs/content/features/supported-css-selectors.md
55+++ b/docs/content/features/supported-css-selectors.md
56@@ -140,6 +140,13 @@
57 | ReducedTranparency | X | NoPreference, Reduce | |
58 | Update | X | Fast, Slow | |
59 
60+## Descriptors
61+| Name | Support | Used by | Note |
62+|-|-|-|-|
63+| style | | @container | |
64+| scroll-state | @container | | |
65+| container | | @container | | Computed using the overall container via window properties (orientation: landscape) and the content-box (min-width: 300px). Supports aspect-ratio, height, orientation, width |
66+
67 ### Media Queries
68 | Name | Support | Usage | Note |
69 |-|-|-|-|
70diff --git a/include/grim.h b/include/grim.h
71index 68b7270..173de14 100755
72--- a/include/grim.h
73+++ b/include/grim.h
74@@ -145,6 +145,81 @@ std::vector<std::vector<std::string>> parseSelectorParts(std::string_view);
75 
76 bool testSelector(Node*, std::vector<std::vector<std::string>>);
77 
78+enum class UnitType {
79+	EQ, // :
80+	LT, // <
81+	GT, // >
82+	LE, // <=
83+	GE, // >=
84+	ADD, // +
85+	SUB, // -
86+	MULT, // *
87+	DIV, // /
88+	HEX,
89+	RGB,
90+	RGBA,
91+	HSL,
92+	HSLA,
93+	HWB,
94+	COLOR,
95+	AND,
96+	OR,
97+	NOT,
98+	ONLY,
99+	COMMA,
100+	PRINT,
101+	SCREEN,
102+	PX,
103+	EM,
104+	PERCENT, // %
105+	CM,
106+	CAP,
107+	CH,
108+	EX,
109+	IC,
110+	LH,
111+	RCAP,
112+	RCH,
113+	REM,
114+	REX,
115+	RIC,
116+	RLH,
117+	VH,
118+	VW,
119+	VMAX,
120+	VMIN,
121+	VB,
122+	VI,
123+	CQW,
124+	CQH,
125+	CQI,
126+	CQB,
127+	CQMIN,
128+	CQMAX,
129+	MM,
130+	Q,
131+	IN,
132+	PC,
133+	PT,
134+	FUNC,
135+	CALC, // need to add all
136+
137+}
138+
139+union UnitValue {
140+	UnitType ENUM;
141+	int INT;
142+	double DOUBLE;
143+	bool BOOL;
144+}
145+
146+struct Unit {
147+	UnitType type;
148+	UnitValue value;
149+	std::vector<Unit> children;
150+
151+}
152+
153 enum class SheetType {
154 	CONTAINER,
155 	COUNTER,
156@@ -273,6 +348,7 @@ class Window {
157 		int width = 0;
158 		int height = 0;
159 		int resolution = 0;
160+		int em = 16;
161 		AnyHover anyHover = AnyHover::Hover;
162 		AnyPointer anyPointer = AnyPointer::Fine;
163 		Orientation orientation = Orientation::Landscape;
164@@ -301,6 +377,10 @@ class Window {
165 			resolution = value;
166 		}
167 
168+		void setEM(int value) {
169+			em = value;
170+		}
171+
172 		void setMouse(AnyPointer pointer) {
173 			if (pointer == AnyPointer::None) {
174 				anyHover = AnyHover::None;
175@@ -341,6 +421,12 @@ class Window {
176 		int getHeight() const {
177 			return height;
178 		}
179+		int getResolution() const {
180+			return resolution;
181+		}
182+		int getEM() const {
183+			return em;
184+		}
185 		double getAspectRatio() const {
186 			if (height == 0) return 0.0;
187 			return static_cast<double>(width) / height;
188diff --git a/src/grim.cc b/src/grim.cc
189index f356404..0fd1b6e 100755
190--- a/src/grim.cc
191+++ b/src/grim.cc
192@@ -23,6 +23,7 @@
193 // |(mnjki) CSS Style Handling                            |
194 // |(jhsfk) Has selection                                 |
195 // |(d678a) Nth child selection                           |
196+// |(7tygl) Query matching 				  |
197 // +------------------------------------------------------+
198 
199 
200@@ -680,6 +681,8 @@ std::vector<std::string> StyleHandler::parseNodeParts(Node* node) {
201 		parts.push_back("."+node->classList.item(i));
202 	}
203 
204+	parts.push_back("*");
205+
206 	return parts;
207 }
208 
209@@ -713,30 +716,27 @@ void Sheet::add(std::string selector, std::unordered_map<std::string, std::strin
210 	}
211 }
212 */
213-/*
214-void getstyle(Node* node, std::vector<std::vector<std::string>> parts, Sheet* sheet, std::unordered_map<std::string, std::string>* styles) {
215+
216+void getstyles(Node* node, std::vector<std::string> node_parts, Sheet* sheet, std::unordered_map<std::string, std::string>* styles) {
217 	std::vector<size_t> canidates;
218 
219 	// Now we have to start from the window.CSS.root, use the basemap to find styles
220-	// | > include a search for "*"
221 	// | test each selector, if a selector matches, go into its children and repeat
222 
223-	for (std::vector<std::string> pt : parts) {
224-		for (std::string p : pt) { 
225-			if (auto sty = sheet->basemap.find(p); sty != sheet->basemap.end()) {
226-				for (auto s : sty->second) {
227-					bool found = false;
228-					// This makes sure we aren't adding the same styles to the candidates list
229-					for (auto c : canidates) {
230-						if (c == s) {
231-							found = true;
232-							break;
233-						}
234-					}
235-					if (!found) {
236-						canidates.push_back(s);
237+	for (std::string p : node_parts) { 
238+		if (auto sty = sheet->basemap.find(p); sty != sheet->basemap.end()) {
239+			for (auto s : sty->second) {
240+				bool found = false;
241+				// This makes sure we aren't adding the same styles to the candidates list
242+				for (auto c : canidates) {
243+					if (c == s) {
244+						found = true;
245+						break;
246 					}
247 				}
248+				if (!found) {
249+					canidates.push_back(s);
250+				}
251 			}
252 		}
253 	}
254@@ -754,12 +754,12 @@ void getstyle(Node* node, std::vector<std::vector<std::string>> parts, Sheet* sh
255 			if (testSelector(node, selector)) {
256 				std::unordered_map<std::string, std::string> props = sheet->children[c].properties;
257 				for (auto p : props) {
258-					styles[p.first] = p.second;
259+					styles->insert(p);
260 				}
261 
262 				// If the Sheet matches then we will repeat the same process with that sheet
263 				if (sheet->children[c].children.size() > 0) {
264-					getstyle(parts, sheet->children[c], styles);
265+					getstyles(node, node_parts, &sheet->children[c], styles);
266 				}
267 			}
268 		} else if (t == SheetType::CONTAINER) {
269@@ -776,17 +776,12 @@ std::unordered_map<std::string, std::string> StyleHandler::getStyles(Node* node)
270 
271 	std::unordered_map<std::string, std::string> styles;
272 
273-	getstyles(node, parts, window.CSS.root, &styles);
274+	getstyles(node, parts, &window->CSS.root, &styles);
275 
276 	// Now we have all styles except the inline styles and the inherited styles
277 
278 }
279 
280-Style StyleHandler::item(int index) {
281-	return styles[index];
282-}
283-*/
284-
285 // Used for root node without a parent
286 const std::vector<std::unique_ptr<Node>> EMPTY_NODE_CHILDREN_VECTOR;
287 
288@@ -1371,3 +1366,23 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
289 
290 	return matched;
291 }
292+
293+// +------------------------------------------------------+
294+// |(7tygl) Query matching 				  |
295+// +------------------------------------------------------+
296+// testQuery takes any sheet class that isn't a SheetType::STYLE
297+// and tries to calculate if the query (ie a media query or 
298+// container query) applies to the node passed
299+bool testQuery(Sheet* query, Node* node, Window* window) {
300+	// First step is to understand the query
301+	// it is parsed from parseSelector parts
302+	// @container scroll-state(scrollable: top) 
303+	// {{" ", "scroll-state(scrollable: top)"}}
304+
305+	//I feel like having string content is going to make things slow
306+
307+
308+	if (query->type == SheetType::CONTAINER) {
309+		
310+	}	
311+}
312diff --git a/src/parser.cc b/src/parser.cc
313index f83d09f..e3c68ca 100755
314--- a/src/parser.cc
315+++ b/src/parser.cc
316@@ -448,9 +448,8 @@ void StyleHandler::parseStream(std::istream& inputStream) {
317 					// If a name is present then remove the name and tag from the selector
318 					// else just remove the @container
319 					if (hasName) {
320-						current->selector[0] = std::vector<std::string>(current->selector[0].begin() + 2, current->selector[0].end());
321+						current->selector[0] = std::vector<std::string>(current->selector[0].begin() + 3, current->selector[0].end());
322 					} else {
323-
324 						current->selector[0] = std::vector<std::string>(current->selector[0].begin() + 1, current->selector[0].end());
325 					}
326 				} else if (parts[0][0] == "@counter-style") {
327diff --git a/tests/css_parser.cc b/tests/css_parser.cc
328index 4f150fe..5bd32c1 100755
329--- a/tests/css_parser.cc
330+++ b/tests/css_parser.cc
331@@ -10,6 +10,7 @@ std::string printSelector(std::vector<std::vector<std::string>> selector) {
332 		for (size_t b = 0; b < selector[a].size(); b++) {
333 			out += selector[a][b];
334 		}
335+		out += ',';
336 	}
337 	return out;
338 }
339@@ -246,18 +247,6 @@ html#nested {
340 
341 }
342 
343-/*
344-
345-TODO:
346-This is redundant because a correct test of this would be:
347-div, class1
348-then
349-.class2
350-then
351-.class3
352-
353-This has been tested above, will need a test on testSelector
354-
355 TEST_CASE("parseCSS can parse multiple selectors nested") {
356 	 std::string cssContent = R"~~~(
357 div, .class1 {
358@@ -277,22 +266,26 @@ div, .class1 {
359 
360 	StyleHandler handler = window.CSS;
361 	SECTION("multi selector test") {
362-		compareStyle("div .class2", {
363-				{"background", "red"}
364-				  }, handler->item(0));
365-		compareStyle(".class1 .class2", {
366+		// This is written kinda weird but it's correct because the CSS above compiles into:
367+		// div .class2 && .class1 .class2
368+		// So [0] should only be .class2 becuse if we are going through the tree the node has already matched on
369+		// div, .class1
370+		// Then the second case is different because we care about the order they are matched in due to &
371+		// So we fully compile the selector
372+		compareStyle(".class2", {
373 				{"background", "red"}
374-				  }, 1, handler->item(1));
375-		compareStyle("div.class3", {
376+				  }, handler.root.children[0].children[0],
377+				  SheetType::STYLE
378+			    );	
379+		compareStyle("div.class3, .class1.class3", {
380 				{"background", "orange"}
381-				  }, 2, handler->item(2));
382-		compareStyle(".class1.class3", {
383-				{"background", "orange"}
384-				  }, 3, handler->item(3));
385-	}
386+				  }, handler.root.children[0].children[1],
387+				  SheetType::STYLE
388+			    );
389+		}
390 
391 }
392-*/
393+
394 
395 TEST_CASE("parseCSSInline can parse inline styles") {
396 	SECTION("parseCSSInline can parse a single property with a ending ;") {