Make some Attrs append instead of replace
This commit is contained in:
parent
3503cc7e9e
commit
cb2a6da25c
1 changed files with 65 additions and 3 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{btree_map::Entry, BTreeMap, HashMap};
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/syntax.html#elements-2>
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
|
@ -101,28 +101,76 @@ pub trait ElementComponent {
|
|||
pub struct Attr {
|
||||
name: String,
|
||||
value: String,
|
||||
append_by: Option<String>,
|
||||
}
|
||||
|
||||
impl Attr {
|
||||
/// Create or replace an attribute.
|
||||
///
|
||||
/// When this attribute is added to an [`Element`] through
|
||||
/// [`ElementComponent::add_to_element`] and an attribute of the same name
|
||||
/// already exists, it replaces that attribute's value.
|
||||
pub fn new(name: impl ToString, value: impl ToString) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
value: value.to_string(),
|
||||
append_by: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create or append to an attribute.
|
||||
///
|
||||
/// When this attribute is added to an [`Element`] through
|
||||
/// [`ElementComponent::add_to_element`] and an attribute of the same name
|
||||
/// already exists, it appends the separator and then its own value to that
|
||||
/// attribute's value.
|
||||
pub fn append(name: impl ToString, value: impl ToString, separator: impl ToString) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
value: value.to_string(),
|
||||
append_by: Some(separator.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create (or replace) a new empty attribute.
|
||||
///
|
||||
/// `Attr::yes(name)` is equivalent to `Attr::new(name, "").`
|
||||
///
|
||||
/// When rendering an empty attribute as HTML, the value can be omitted:
|
||||
/// `name=""` is equivalent to just `name`.
|
||||
pub fn yes(name: impl ToString) -> Self {
|
||||
Self::new(name, "")
|
||||
}
|
||||
|
||||
/// Create (or replace) an `id` attribute.
|
||||
///
|
||||
/// `Attr::id(id)` is equivalent to `Attr::new("id", id)`.
|
||||
pub fn id(id: impl ToString) -> Self {
|
||||
Self::new("id", id)
|
||||
}
|
||||
|
||||
/// Create (or append) to a `class` attribute.
|
||||
///
|
||||
/// `Attr::class(class)` is equivalent to
|
||||
/// `Attr::append("class", class, " ")`.
|
||||
pub fn class(class: impl ToString) -> Self {
|
||||
Self::new("class", class)
|
||||
Self::append("class", class, " ")
|
||||
}
|
||||
|
||||
/// Create (or append) to a `style` attribute.
|
||||
///
|
||||
/// `Attr::style(style)` is equivalent to
|
||||
/// `Attr::append("style", style, ";")`.
|
||||
pub fn style(style: impl ToString) -> Self {
|
||||
Self::append("style", style, ";")
|
||||
}
|
||||
|
||||
/// Create (or replace) a new [`data-*` attribute][mdn].
|
||||
///
|
||||
/// `Attr::data(name, value)` is equivalent to
|
||||
/// `Attr::new(format!("data-{name}"), value)`.
|
||||
///
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*
|
||||
pub fn data(name: impl ToString, value: impl ToString) -> Self {
|
||||
Self::new(format!("data-{}", name.to_string()), value)
|
||||
}
|
||||
|
|
@ -133,7 +181,21 @@ impl ElementComponent for Attr {
|
|||
if element.kind != ElementKind::Foreign {
|
||||
self.name = self.name.to_ascii_lowercase();
|
||||
}
|
||||
element.attributes.insert(self.name, self.value);
|
||||
match element.attributes.entry(self.name) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(self.value);
|
||||
}
|
||||
Entry::Occupied(mut entry) => match self.append_by {
|
||||
None => {
|
||||
entry.insert(self.value);
|
||||
}
|
||||
Some(sep) => {
|
||||
let value = entry.get_mut();
|
||||
value.push_str(&sep);
|
||||
value.push_str(&self.value);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue