Change access to VList children to a wrapper (#2673)

this should avoid having to manually call recheck_fully_keyed

* add mutable accessor to children
* fix workflow
* fix markdown example
* remove recheck_fully_keyed
This commit is contained in:
WorldSEnder 2022-05-11 12:37:39 +02:00 committed by GitHub
parent 3760c5f8b5
commit d7b43bbc26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 32 deletions

View File

@ -53,31 +53,34 @@ pub fn render_markdown(src: &str) -> Html {
pre.add_child(top.into()); pre.add_child(top.into());
top = pre; top = pre;
} else if let Tag::Table(aligns) = tag { } else if let Tag::Table(aligns) = tag {
for r in top.children_mut().iter_mut().flat_map(|ch| ch.iter_mut()) { if let Some(top_children) = top.children_mut() {
if let VNode::VTag(ref mut vtag) = r { for r in top_children.children_mut().iter_mut() {
for (i, c) in vtag if let VNode::VTag(ref mut vtag) = r {
.children_mut() if let Some(vtag_children) = vtag.children_mut() {
.iter_mut() for (i, c) in
.flat_map(|ch| ch.iter_mut()) vtag_children.children_mut().iter_mut().enumerate()
.enumerate() {
{ if let VNode::VTag(ref mut vtag) = c {
if let VNode::VTag(ref mut vtag) = c { match aligns[i] {
match aligns[i] { Alignment::None => {}
Alignment::None => {} Alignment::Left => add_class(vtag, "text-left"),
Alignment::Left => add_class(vtag, "text-left"), Alignment::Center => add_class(vtag, "text-center"),
Alignment::Center => add_class(vtag, "text-center"), Alignment::Right => add_class(vtag, "text-right"),
Alignment::Right => add_class(vtag, "text-right"), }
}
} }
} }
} }
} }
} }
} else if let Tag::TableHead = tag { } else if let Tag::TableHead = tag {
for c in top.children_mut().iter_mut().flat_map(|ch| ch.iter_mut()) { if let Some(top_children) = top.children_mut() {
if let VNode::VTag(ref mut vtag) = c { for c in top_children.children_mut().iter_mut() {
// TODO if let VNode::VTag(ref mut vtag) = c {
// vtag.tag = "th".into(); // TODO
vtag.add_attribute("scope", "col"); // vtag.tag = "th".into();
vtag.add_attribute("scope", "col");
}
} }
} }
} }

View File

@ -29,13 +29,42 @@ impl Deref for VList {
} }
} }
impl DerefMut for VList { /// Mutable children of a [VList].
fn deref_mut(&mut self) -> &mut Self::Target { ///
// Caller might change the keys of the VList or add unkeyed children. /// This struct has a `DerefMut` implementations into [`Vec<VNode>`](std::vec::Vec).
// Defensively assume they will. /// Prefer to use immutable access, since this re-checks if all nodes have keys when dropped.
self.fully_keyed = false; pub struct ChildrenMut<'a> {
children: &'a mut Vec<VNode>,
fully_keyed: &'a mut bool,
}
&mut self.children impl<'a> Deref for ChildrenMut<'a> {
type Target = Vec<VNode>;
fn deref(&self) -> &Self::Target {
self.children
}
}
impl<'a> DerefMut for ChildrenMut<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
*self.fully_keyed = false;
self.children
}
}
impl<'a> Drop for ChildrenMut<'a> {
fn drop(&mut self) {
if !*self.fully_keyed {
// Caller might have changed the keys of the VList or add unkeyed children.
*self.fully_keyed = self.children.iter().all(|ch| ch.has_key());
}
}
}
impl<'a> std::fmt::Debug for ChildrenMut<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("ChildrenMut").field(&self.children).finish()
} }
} }
@ -76,12 +105,42 @@ impl VList {
} }
} }
/// Recheck, if the all the children have keys. /// Get a mutable list of children in this vlist.
/// pub fn children_mut(&mut self) -> ChildrenMut<'_> {
/// Run this, after modifying the child list that contained only keyed children prior to the ChildrenMut {
/// mutable dereference. children: &mut self.children,
pub fn recheck_fully_keyed(&mut self) { fully_keyed: &mut self.fully_keyed,
self.fully_keyed = self.children.iter().all(|ch| ch.has_key()); }
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::virtual_dom::{VTag, VText};
#[test]
fn mutably_change_children() {
let mut vlist = VList::new();
assert!(vlist.fully_keyed, "should start fully keyed");
// add a child that is keyed
let mut children = vlist.children_mut();
children.push(VNode::VTag({
let mut tag = VTag::new("a");
tag.key = Some(42u32.into());
Box::new(tag)
}));
drop(children);
assert!(vlist.fully_keyed, "should still be fully keyed");
assert_eq!(vlist.len(), 1, "should contain 1 child");
// now add a child that is not keyed
let mut children = vlist.children_mut();
children.push(VNode::VText(VText::new("lorem ipsum")));
drop(children);
assert!(
!vlist.fully_keyed,
"should not be fully keyed, text tags have no key"
);
} }
} }

View File

@ -9,7 +9,7 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
chrono = "0.4" chrono = "0.4"
git2 = "0.14" git2 = "=0.14.2" # see https://github.com/rust-lang/git2-rs/issues/838 fixed with MSRV 1.60
regex = "1" regex = "1"
reqwest = { version = "0.11", features = ["blocking", "json"] } reqwest = { version = "0.11", features = ["blocking", "json"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }