about summary refs log tree commit diff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs77
1 files changed, 76 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs
index df7eead..18836d0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
 use core::fmt;
+use query::{parse_query, QueryComponent, QueryElement, QueryParseError};
 use tag::Tag;
 
 mod query;
@@ -25,10 +26,84 @@ impl Html {
 		}
 	}
 
-	pub fn query<S: AsRef<str>>(&self, query: S) -> Option<&Node> {
+	pub fn query<S: AsRef<str>>(&self, query: S) -> Result<Option<&Node>, QueryParseError> {
+		let query = parse_query(query.as_ref())?;
+
+		let mut working: Vec<&Node> = self.nodes.iter().collect();
+
+		for component in &query {
+			let component_working: Vec<&Node> = std::mem::take(&mut working);
+			for node in component_working {
+				match component {
+					QueryComponent::DirectElement(direct) => {
+						if Self::node_matches(node, direct) {
+							working.push(node);
+						}
+					}
+					QueryComponent::Element(element) => {
+						// GENNY:
+						// you were working on the query system. This one needs to recur,
+						// checking the current component against the entire depth of
+						// children of the node. I'm worried about lifetimes here. For
+						// immutable we might be alright but what happens when we're
+						// muteable and we want to return a parent and it's child because
+						// they both match?
+						//
+						// Don't get discouraged; it's a hard problem. Perhaps we write an
+						// iterator so we don't have to keep references around? Sticking
+						// everything in an Rc or whatever structure I'd need feels icky.
+						//
+						// Perhaps it's the way I'm searching. I could recur through the
+						// current node, from self.nodes, until match failure. It fits
+						// the funciton signature, returning one Node, but perhaps doesn't
+						// fit the purpose.
+						//
+						// But the purpose is to easily insert parsed text into HTML
+						// without templating it, so maybe it is fit for purpose. That
+						// only needs to find one element at a time perhaps.
+						//
+						// All goes sour maybe I can return IDs to nodes? Keep a counter
+						// in HTML where each node gets an increasing ID. Pass the ID to
+						// a funtion in HTML for modification. Or maybe have IDs,
+						// NodeHandles let's call them, contain an Rc<RefCell<Html>>.
+						//
+						// That is by far enough thinking for the night. It's time to
+						// head to bed. <3 i love you
+						todo!()
+					}
+				}
+			}
+		}
+
 		todo!()
 	}
 
+	fn node_matches(node: &Node, component: &QueryElement) -> bool {
+		if let Node::Tag(tag) = node {
+			if let Some(comp_name) = component.tag.as_deref() {
+				if comp_name != tag.name {
+					return false;
+				}
+			}
+
+			match (tag.id(), component.id.as_deref()) {
+				(None, Some(_)) => return false,
+				(Some(tag_id), Some(comp_id)) if tag_id != comp_id => return false,
+				_ => (),
+			}
+
+			if let Some(comp_class) = component.class.as_deref() {
+				if !tag.has_class(comp_class) {
+					return false;
+				}
+			}
+
+			true
+		} else {
+			false
+		}
+	}
+
 	fn parse_node(raw: &str) -> Consumed {
 		match Self::is_tag(raw) {
 			Some(_) => {