home readme diff tree note docs

0commit 5cf22848ea3b4e97961ad80f45f4a38f7a0a54ab
1Author: Mason Wright <mason@lakefox.net>
2Date:   Sun Jul 13 18:41:04 2025 -0600
3
4    StyleList is tested
5
6diff --git a/include/grim.h b/include/grim.h
7index d10e9d0..744ffa5 100644
8--- a/include/grim.h
9+++ b/include/grim.h
10@@ -107,6 +107,7 @@ class Node {
11 				StyleList(Node* node) : self(node) {}
12 				std::string get(std::string key);
13 				void set(std::string key, std::string value);
14+				void remove(std::string key);
15 				std::pair<std::string, std::string> item(size_t index);
16 				size_t length();
17 		};
18diff --git a/src/grim.cc b/src/grim.cc
19index a6975b6..846449f 100755
20--- a/src/grim.cc
21+++ b/src/grim.cc
22@@ -306,7 +306,11 @@ void Node::StyleList::createIndex() {
23 			if (keyFound) {
24 				if (secondNonWhiteSpace) {
25 					if (s == ';' || i >= len-1) {
26-						end = i;
27+						if (i >= len-1 && s != ';') {
28+							end = i+1;
29+						} else {
30+							end = i;
31+						}
32 						indexes.push_back({firstLetter, splitPoint, end});
33 						firstNonWhiteSpace = false;
34 						secondNonWhiteSpace = false;
35@@ -354,11 +358,11 @@ std::pair<std::string, std::string> Node::StyleList::item(size_t index) {
36 
37 	int f = std::get<0>(indexes[index]);
38 	int s = std::get<1>(indexes[index]);
39-	property.first = styles.substr(f, f-s);
40+	property.first = styles.substr(f, s-f);
41 	trimSpace(property.first);
42 
43 	int t = std::get<2>(indexes[index]);
44-	property.second = styles.substr(s, t-s);
45+	property.second = styles.substr(s+1, t-(s+1));
46 	trimSpace(property.second);
47 	return property;
48 
49@@ -396,15 +400,48 @@ void Node::StyleList::set(std::string key, std::string value) {
50 		createIndex();
51 	}
52 	std::string styles = self->attributes["style"];
53+
54 	for (size_t i = 0; i < indexes.size(); i++) {
55 		int f = std::get<0>(indexes[i]);
56 		int s = std::get<1>(indexes[i]);
57-		std::string slicedKey = styles.substr(f, f-s);
58+		std::string slicedKey = styles.substr(f, s-f);
59 		trimSpace(slicedKey);
60 		if (slicedKey == key) {
61 			int t = std::get<2>(indexes[i]);
62 			self->attributes["style"] = styles.substr(0, f) +" "+key+":"+value+";"+styles.substr(t);
63-			break;
64+			// Return early to skip the appending value;
65+			return;
66+		}
67+	}
68+
69+	// If the property wasn't replaced then add it
70+	
71+	char lastChar = styles[std::get<2>(indexes[indexes.size()-1])];
72+
73+	if (lastChar == ';') {
74+		self->attributes["style"] += " "+key+":"+value+";";
75+	} else {
76+		// If the user didn't terminate the last style
77+		// terminate it for them
78+		self->attributes["style"] += "; "+key+":"+value+";";
79+	}
80+}
81+
82+void Node::StyleList::remove(std::string key) {
83+	if (!checkIndex()) {
84+		createIndex();
85+	}
86+	std::string styles = self->attributes["style"];
87+
88+	for (size_t i = 0; i < indexes.size(); i++) {
89+		int f = std::get<0>(indexes[i]);
90+		int s = std::get<1>(indexes[i]);
91+		std::string slicedKey = styles.substr(f, s-f);
92+		trimSpace(slicedKey);
93+		if (slicedKey == key) {
94+			int t = std::get<2>(indexes[i]);
95+			self->attributes["style"] = styles.substr(0, f) + styles.substr(t);
96+			return;
97 		}
98 	}
99 }
100@@ -728,7 +765,6 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
101 	// By the time we get here, we know the right most selector some what matches
102 	// so now if it is a compound selector we should see if the parent('s) some what match
103 
104-	// !TODO: Add support for *
105 	if (selector.size() > 1) {
106 		// If a selector is made up of several different selectors
107 		// ie {{"h1"}, {"h2"}, {"h3"}}
108diff --git a/tests/html_node.cc b/tests/html_node.cc
109index bcddce2..4f5a4d6 100644
110--- a/tests/html_node.cc
111+++ b/tests/html_node.cc
112@@ -82,4 +82,56 @@ TEST_CASE("StyleList", "[html]") {
113 		REQUIRE(div->style.get("background") == "white");
114 		REQUIRE(div->style.get("font-size") == "12px");
115 	}
116+
117+	SECTION("StyleList can change an existing property") {
118+		div->style.set("background", "red");
119+
120+		REQUIRE(div->style.get("background") == "red");
121+	}
122+
123+	SECTION("StyleList can add a new property") {
124+		div->style.set("color", "black");
125+
126+		REQUIRE(div->style.get("color") == "black");
127+		REQUIRE(div->style.get("background") == "white");
128+		REQUIRE(div->style.get("font-size") == "12px");
129+	}
130+
131+	SECTION("StyleList can add a new property without a ending ;") {
132+		div->setAttribute("style", "background: white; font-size: 12px");
133+
134+		div->style.set("color", "black");
135+
136+		REQUIRE(div->style.get("color") == "black");
137+		REQUIRE(div->style.get("background") == "white");
138+		REQUIRE(div->style.get("font-size") == "12px");
139+	}
140+
141+	SECTION("StyleList can remove a property") {
142+		div->style.remove("font-size");
143+
144+		REQUIRE(div->style.get("background") == "white");
145+		REQUIRE(div->style.get("font-size") == "");
146+	}
147+
148+	SECTION("StyleList can remove a property without a ending ;") {
149+		div->setAttribute("style", "background: white; font-size: 12px");
150+
151+		div->style.remove("font-size");
152+
153+		REQUIRE(div->style.get("background") == "white");
154+		REQUIRE(div->style.get("font-size") == "");
155+	}
156+
157+	SECTION("StyleList can itterate through all styles") {
158+		REQUIRE(div->style.length() == 2);
159+
160+		auto bg = div->style.item(0);
161+		REQUIRE(bg.first == "background");
162+		REQUIRE(bg.second == "white");
163+
164+		auto fs = div->style.item(1);
165+		REQUIRE(fs.first == "font-size");
166+		REQUIRE(fs.second == "12px");
167+	}
168 }