///|
/// Element interface for selector matching
/// This represents a DOM-like element with the information needed for CSS selector matching
///|
/// Attribute value on an element
pub(all) struct Attribute {
name : String
value : String
}
///|
/// Element data for selector matching
/// This is a concrete type that can be used with or without a real DOM
pub(all) struct Element {
/// Tag name (lowercase, e.g. "div", "span")
tag_name : String
/// ID attribute (without #)
id : String?
/// Class names (without .)
classes : Array[String]
/// Other attributes
attributes : Array[Attribute]
/// Custom element states for :state()
custom_states : Array[String]
/// Parent element (for ancestor/parent selectors)
parent : Element?
/// Previous sibling (for adjacent/general sibling selectors)
prev_sibling : Element?
/// Next sibling
next_sibling : Element?
/// Child elements
children : Array[Element]
/// Index among siblings (1-based for :nth-child)
sibling_index : Int
/// Total number of siblings (for :last-child, :nth-last-child)
sibling_count : Int
}
///|
/// Create a new element with minimal information
pub fn Element::new(tag_name : String) -> Element {
{
tag_name,
id: None,
classes: [],
attributes: [],
custom_states: [],
parent: None,
prev_sibling: None,
next_sibling: None,
children: [],
sibling_index: 1,
sibling_count: 1,
}
}
///|
/// Create an element with id
pub fn Element::with_id(tag_name : String, id : String) -> Element {
{
tag_name,
id: Some(id),
classes: [],
attributes: [],
custom_states: [],
parent: None,
prev_sibling: None,
next_sibling: None,
children: [],
sibling_index: 1,
sibling_count: 1,
}
}
///|
/// Create an element with classes
pub fn Element::with_classes(
tag_name : String,
classes : Array[String],
) -> Element {
{
tag_name,
id: None,
classes,
attributes: [],
custom_states: [],
parent: None,
prev_sibling: None,
next_sibling: None,
children: [],
sibling_index: 1,
sibling_count: 1,
}
}
///|
/// Get attribute value by name
pub fn Element::get_attribute(self : Element, name : String) -> String? {
for attr in self.attributes {
if attr.name == name {
return Some(attr.value)
}
}
None
}
///|
/// Check if element has a specific class
pub fn Element::has_class(self : Element, class_name : String) -> Bool {
for cls in self.classes {
if cls == class_name {
return true
}
}
false
}
///|
/// Check if element is first child
pub fn Element::is_first_child(self : Element) -> Bool {
self.sibling_index == 1
}
///|
/// Check if element is last child
pub fn Element::is_last_child(self : Element) -> Bool {
self.sibling_index == self.sibling_count
}
///|
/// Builder for creating elements with fluent API
pub fn Element::set_id(self : Element, id : String) -> Element {
{ ..self, id: Some(id) }
}
///|
pub fn Element::add_class(self : Element, class_name : String) -> Element {
let classes = self.classes.copy()
classes.push(class_name)
{ ..self, classes, }
}
///|
pub fn Element::set_attribute(
self : Element,
name : String,
value : String,
) -> Element {
let attributes = self.attributes.copy()
attributes.push({ name, value })
{ ..self, attributes, }
}
///|
pub fn Element::add_custom_state(self : Element, state : String) -> Element {
let custom_states = self.custom_states.copy()
custom_states.push(state)
{ ..self, custom_states, }
}
///|
pub fn Element::set_sibling_info(
self : Element,
index : Int,
count : Int,
) -> Element {
{ ..self, sibling_index: index, sibling_count: count }
}
///|
pub fn Element::set_parent(self : Element, parent : Element) -> Element {
{ ..self, parent: Some(parent) }
}