diff --git a/crates/benilla-ui/src/framexml.rs b/crates/benilla-ui/src/framexml.rs index 0e1cdfe1..0296fd23 100644 --- a/crates/benilla-ui/src/framexml.rs +++ b/crates/benilla-ui/src/framexml.rs @@ -315,8 +315,10 @@ fn element_from_node(node: roxmltree::Node) -> Element { /// attributes override or extend the template's (case-insensitively). The reference merges /// nothing: `LoadXML` re-enters itself on the one object against each template, the most distant /// first, then the instance (`0x76985c`; `` repeat the walk, `0x76a060`), and reads `name` -/// and `id` from the instance alone (`PreLoadXML 0x769770`). Here `name` and `virtual` merge like -/// any attribute. A cycle is skipped with a warning. +/// and `id` from the instance alone (`PreLoadXML 0x769770`; a region's factory reads its `name` +/// once, outside the walk, `0x6f2751`/`0x6f27e1`). So here `name` and `id` come from the element +/// alone, and an unnamed instance stays unnamed; `virtual` merges like any attribute, read only at +/// registration. A cycle is skipped with a warning. pub fn expand( element: &Element, templates: &HashMap<&str, &Element>, @@ -390,9 +392,15 @@ fn expand_inner( } } -/// [`expand`]'s merge; `over`'s tag wins, and its body when it has one. +/// [`expand`]'s merge; `over`'s tag wins, and its body when it has one. `base`'s `name` and `id` +/// are dropped: they belong to the node they are written on. fn merge(base: &Element, over: &Element) -> Element { - let mut attrs = base.attrs.clone(); + let mut attrs: Vec<(String, String)> = base + .attrs + .iter() + .filter(|(k, _)| !k.eq_ignore_ascii_case("name") && !k.eq_ignore_ascii_case("id")) + .cloned() + .collect(); for (k, v) in &over.attrs { if let Some(slot) = attrs.iter_mut().find(|(ek, _)| ek.eq_ignore_ascii_case(k)) { slot.1 = v.clone(); diff --git a/crates/benilla-ui/src/loader/mod.rs b/crates/benilla-ui/src/loader/mod.rs index 1084f84f..0e6d9d6c 100644 --- a/crates/benilla-ui/src/loader/mod.rs +++ b/crates/benilla-ui/src/loader/mod.rs @@ -898,5 +898,7 @@ pub(super) fn font_object_from_element(el: &Element) -> FontObject { } } +#[cfg(test)] +mod template_name_tests; #[cfg(test)] mod tests; diff --git a/crates/benilla-ui/src/loader/template_name_tests.rs b/crates/benilla-ui/src/loader/template_name_tests.rs new file mode 100644 index 00000000..f0e12d21 --- /dev/null +++ b/crates/benilla-ui/src/loader/template_name_tests.rs @@ -0,0 +1,87 @@ +//! `name=` and `id=` belong to the node they are written on: `PreLoadXML 0x769770` reads them from +//! the instance before `LoadXML` walks its templates (`0x76985c`), and the region factories read +//! `name` once, outside that walk (`0x6f2751`, `0x6f27e1`). + +use crate::framexml; +use crate::loader::load; +use crate::script::UiScript; + +const DOC: &str = r#" + + + + + + + + + + + + + +