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 ;") {