textlane_html/actions/attribute/
write.rs1use textlane_core::hast::{Element, PropertyItem, PropertyValue};
2use textlane_core::{Allocator, ArenaVec};
3
4use crate::helpers::property::find_property;
5use crate::helpers::schema::{
6 BOOLEAN, COMMA_OR_SPACE_SEPARATED, COMMA_SEPARATED, HTML, NUMBER, OVERLOADED_BOOLEAN,
7 SPACE_SEPARATED,
8};
9use crate::helpers::value::set_property;
10
11pub fn write_attribute<'a>(
14 element: &mut Element<'a>,
15 name: &str,
16 value: &str,
17 alloc: &'a Allocator,
18) {
19 let found = find_property(&HTML, name);
20 let kinds = found.kinds;
21 let value = if kinds & (BOOLEAN | OVERLOADED_BOOLEAN) != 0
22 && (value.is_empty() || value.eq_ignore_ascii_case(&found.attribute))
23 {
24 PropertyValue::Boolean(true)
25 } else if kinds & (SPACE_SEPARATED | COMMA_SEPARATED | COMMA_OR_SPACE_SEPARATED) != 0
26 {
27 let comma = kinds & COMMA_SEPARATED != 0;
28 let mut list = ArenaVec::new_in(alloc);
29 let words: Vec<&str> = match comma {
30 true => value.split(',').map(str::trim).collect(),
31 false => value.split_ascii_whitespace().collect(),
32 };
33 for word in words.into_iter().filter(|word| !word.is_empty()) {
34 list.push(PropertyItem::String(alloc.alloc_str(word)));
35 }
36 PropertyValue::List(list)
37 } else if kinds & NUMBER != 0
38 && let Ok(number) = value.trim().parse::<f64>()
39 {
40 PropertyValue::Number(number)
41 } else {
42 PropertyValue::String(alloc.alloc_str(value))
43 };
44 set_property(element, alloc.alloc_str(&found.property), value);
45}
46
47#[cfg(test)]
48#[path = "write_unit.rs"]
49mod unit;