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>
|
/// <https://html.spec.whatwg.org/multipage/syntax.html#elements-2>
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
@ -101,28 +101,76 @@ pub trait ElementComponent {
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
name: String,
|
name: String,
|
||||||
value: String,
|
value: String,
|
||||||
|
append_by: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attr {
|
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 {
|
pub fn new(name: impl ToString, value: impl ToString) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value: value.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 {
|
pub fn yes(name: impl ToString) -> Self {
|
||||||
Self::new(name, "")
|
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 {
|
pub fn id(id: impl ToString) -> Self {
|
||||||
Self::new("id", id)
|
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 {
|
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 {
|
pub fn data(name: impl ToString, value: impl ToString) -> Self {
|
||||||
Self::new(format!("data-{}", name.to_string()), value)
|
Self::new(format!("data-{}", name.to_string()), value)
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +181,21 @@ impl ElementComponent for Attr {
|
||||||
if element.kind != ElementKind::Foreign {
|
if element.kind != ElementKind::Foreign {
|
||||||
self.name = self.name.to_ascii_lowercase();
|
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