use crate::util::Utf16String;
use crate::util::string_case_utils::to_lower_case_default;
use super::{ElementName, ElementNameError, ElementNameKind};
pub struct HTMLElementName {
element_name: ElementName,
complete_namespaced_element_name: Utf16String,
complete_html5_element_name: Utf16String,
}
impl HTMLElementName {
pub(super) fn for_name(
prefix: Option<Utf16String>,
element_name: Option<Utf16String>,
) -> Result<Self, ElementNameError> {
let normalized_element = element_name.filter(|value| !value.is_empty()).map_or_else(
|| Utf16String::from_utf16(Vec::new()),
|value| to_lower_case_default(&value),
);
let normalized_prefix = prefix
.as_ref()
.filter(|value| !value.is_empty())
.map(to_lower_case_default);
let (namespaced, html5, complete_names) = if let Some(prefix) = normalized_prefix.as_ref() {
let namespaced = join(prefix, b':', &normalized_element, None);
let html5 = join(prefix, b'-', &normalized_element, None);
(
namespaced.clone(),
html5.clone(),
vec![Some(namespaced), Some(html5)],
)
} else {
(
normalized_element.clone(),
normalized_element.clone(),
vec![Some(normalized_element.clone())],
)
};
let base = ElementName::new(
ElementNameKind::Html,
normalized_prefix,
Some(normalized_element),
complete_names,
)?;
Ok(Self {
element_name: base,
complete_namespaced_element_name: namespaced,
complete_html5_element_name: html5,
})
}
#[must_use]
pub const fn as_element_name(&self) -> &ElementName {
&self.element_name
}
#[must_use]
pub const fn get_complete_namespaced_element_name(&self) -> &Utf16String {
&self.complete_namespaced_element_name
}
#[must_use]
pub const fn get_complete_html5_element_name(&self) -> &Utf16String {
&self.complete_html5_element_name
}
}
fn join(
prefix: &Utf16String,
separator: u8,
name: &Utf16String,
leading: Option<&str>,
) -> Utf16String {
let mut result = leading.map_or_else(Vec::new, |value| value.encode_utf16().collect());
result.extend_from_slice(prefix.as_utf16());
result.push(u16::from(separator));
result.extend_from_slice(name.as_utf16());
Utf16String::from_utf16(result)
}