on master help sign in
PR feedback
8b4eafcRyan Levick
src/builder.rs+31−19
@@ -64,18 +64,6 @@ impl<'a>
64 namespace: None,
64 namespace: None,
65 }
65 }
66 }
66 }
67−
68− /// FIX ME
69− pub fn new_with_namespace(bump: &'a Bump, tag_name: &'a str, namespace: &'a str) -> Self {
70− ElementBuilder {
71− bump,
72− tag_name,
73− listeners: bumpalo::collections::Vec::new_in(bump),
74− attributes: bumpalo::collections::Vec::new_in(bump),
75− children: bumpalo::collections::Vec::new_in(bump),
76− namespace: Some(namespace),
77− }
78− }
79}
67}
80
68
81impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
69impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
@@ -202,6 +190,32 @@ where
202 }
190 }
203 }
191 }
204
192
193+ /// Set the namespace for this element.
194+ ///
195+ /// # Example
196+ ///
197+ /// ```no_run
198+ /// use dodrio::{builder::*, bumpalo::Bump};
199+ ///
200+ /// let b = Bump::new();
201+ ///
202+ /// // Create a `<td>` tag with an xhtml namespace
203+ /// let my_div = td(&b)
204+ /// .namepace(Some("http://www.w3.org/1999/xhtml"))
205+ /// .finish();
206+ /// ```
207+ #[inline]
208+ pub fn namespace(self, namespace: Option<&'a str>) -> Self {
209+ ElementBuilder {
210+ bump: self.bump,
211+ tag_name: self.tag_name,
212+ listeners: self.listeners,
213+ attributes: self.attributes,
214+ children: self.children,
215+ namespace,
216+ }
217+ }
218+
205 /// Create the virtual DOM node described by this builder.
219 /// Create the virtual DOM node described by this builder.
206 ///
220 ///
207 /// # Example
221 /// # Example
@@ -219,17 +233,14 @@ where
219 /// ```
233 /// ```
220 #[inline]
234 #[inline]
221 pub fn finish(self) -> Node<'a> {
235 pub fn finish(self) -> Node<'a> {
222− let element = Node::element_node(
236+ Node::element(
223 self.bump,
237 self.bump,
224 self.tag_name,
238 self.tag_name,
225 self.listeners,
239 self.listeners,
226 self.attributes,
240 self.attributes,
227 self.children,
241 self.children,
228− );
229− match self.namespace {
242+ self.namespace,
230− Some(namespace) => Node::NamespacedElement(namespace, element),
243+ )
231− None => Node::Element(element),
232− }
233 }
244 }
234}
245}
235
246
@@ -394,7 +405,8 @@ macro_rules! builder_constructors {
394 bumpalo::collections::Vec<'a, Attribute<'a>>,
405 bumpalo::collections::Vec<'a, Attribute<'a>>,
395 bumpalo::collections::Vec<'a, Node<'a>>,
406 bumpalo::collections::Vec<'a, Node<'a>>,
396 > {
407 > {
397− ElementBuilder::new_with_namespace(bump, stringify!($name), $namespace)
408+ let builder = ElementBuilder::new(bump, stringify!($name));
409+ builder.namespace(Some($namespace))
398 }
410 }
399 )*
411 )*
400 }
412 }
src/node.rs+5−23
@@ -11,9 +11,6 @@ pub enum Node<'a> {
11
11
12 /// An element potentially with attributes and children.
12 /// An element potentially with attributes and children.
13 Element(ElementNode<'a>),
13 Element(ElementNode<'a>),
14−
15− /// An element with a namespace and potentially with attributes and children.
16− NamespacedElement(&'a str, ElementNode<'a>),
17}
14}
18
15
19/// Text nodes are just a string of text. They cannot have attributes or
16/// Text nodes are just a string of text. They cannot have attributes or
@@ -31,6 +28,7 @@ pub struct ElementNode<'a> {
31 pub(crate) listeners: &'a [Listener<'a>],
28 pub(crate) listeners: &'a [Listener<'a>],
32 pub(crate) attributes: &'a [Attribute<'a>],
29 pub(crate) attributes: &'a [Attribute<'a>],
33 pub(crate) children: &'a [Node<'a>],
30 pub(crate) children: &'a [Node<'a>],
31+ pub(crate) namespace: Option<&'a str>,
34}
32}
35
33
36/// An event listener callback function.
34/// An event listener callback function.
@@ -106,25 +104,8 @@ impl<'a> Node<'a> {
106 listeners: Listeners,
104 listeners: Listeners,
107 attributes: Attributes,
105 attributes: Attributes,
108 children: Children,
106 children: Children,
107+ namespace: Option<&'a str>,
109 ) -> Node<'a>
108 ) -> Node<'a>
110− where
111− Listeners: 'a + AsRef<[Listener<'a>]>,
112− Attributes: 'a + AsRef<[Attribute<'a>]>,
113− Children: 'a + AsRef<[Node<'a>]>,
114− {
115− let element_node = Node::element_node(bump, tag_name, listeners, attributes, children);
116− Node::Element(element_node)
117− }
118−
119− /// Construct a new element node with the given tag name and children.
120− #[inline]
121− pub(crate) fn element_node<Listeners, Attributes, Children>(
122− bump: &'a Bump,
123− tag_name: &'a str,
124− listeners: Listeners,
125− attributes: Attributes,
126− children: Children,
127− ) -> ElementNode<'a>
128 where
109 where
129 Listeners: 'a + AsRef<[Listener<'a>]>,
110 Listeners: 'a + AsRef<[Listener<'a>]>,
130 Attributes: 'a + AsRef<[Attribute<'a>]>,
111 Attributes: 'a + AsRef<[Attribute<'a>]>,
@@ -139,12 +120,13 @@ impl<'a> Node<'a> {
139 let attributes: &'a Attributes = bump.alloc(attributes);
120 let attributes: &'a Attributes = bump.alloc(attributes);
140 let attributes: &'a [Attribute<'a>] = attributes.as_ref();
121 let attributes: &'a [Attribute<'a>] = attributes.as_ref();
141
122
142− ElementNode {
123+ Node::Element(ElementNode {
143 tag_name,
124 tag_name,
144 listeners,
125 listeners,
145 attributes,
126 attributes,
146 children,
127 children,
128+ namespace,
147− }
129+ })
148 }
130 }
149
131
150 /// Is this node a text node?
132 /// Is this node a text node?
src/vdom.rs+17−47
@@ -138,7 +138,7 @@ impl Vdom {
138 container.set_inner_html("");
138 container.set_inner_html("");
139
139
140 // Create a dummy `<div/>` in our container.
140 // Create a dummy `<div/>` in our container.
141− let current_root = Node::element(&dom_buffers[0], "div", [], [], []);
141+ let current_root = Node::element(&dom_buffers[0], "div", [], [], [], None);
142 let current_root = Some(unsafe { extend_node_lifetime(current_root) });
142 let current_root = Some(unsafe { extend_node_lifetime(current_root) });
143 let window = web_sys::window().expect("should have acess to the Window");
143 let window = web_sys::window().expect("should have acess to the Window");
144 let document = window
144 let document = window
@@ -287,43 +287,32 @@ impl VdomInnerExclusive {
287 self.change_list.emit_set_text(new_text);
287 self.change_list.emit_set_text(new_text);
288 }
288 }
289 }
289 }
290− (&Node::Text(_), Node::Element(_))
290+ (&Node::Text(_), Node::Element(_)) => {
291− | (&Node::Text(_), Node::NamespacedElement(_, _)) => {
292 debug!(" replacing a text node with an element");
291 debug!(" replacing a text node with an element");
293 self.create(registry, new);
292 self.create(registry, new);
294 self.change_list.emit_replace_with();
293 self.change_list.emit_replace_with();
295 }
294 }
296− (&Node::Element(_), Node::Text(_))
295+ (&Node::Element(_), Node::Text(_)) => {
297− | (&Node::NamespacedElement(_, _), Node::Text(_)) => {
298 debug!(" replacing an element with a text node");
296 debug!(" replacing an element with a text node");
299 self.create(registry, new);
297 self.create(registry, new);
300 self.change_list.emit_replace_with();
298 self.change_list.emit_replace_with();
301 }
299 }
302− (&Node::Element(ref new_element_node), Node::Element(ref old_element_node))
300+ (
303− | (
304− &Node::NamespacedElement(_, ref new_element_node),
305− Node::Element(ref old_element_node),
306− )
307− | (
308− &Node::Element(ref new_element_node),
309− Node::NamespacedElement(_, ref old_element_node),
310− )
311− | (
312− &Node::NamespacedElement(_, ref new_element_node),
313− Node::NamespacedElement(_, ref old_element_node),
314− ) => {
315− let ElementNode {
301+ &Node::Element(ElementNode {
316 tag_name: new_tag_name,
302 tag_name: new_tag_name,
317 listeners: new_listeners,
303 listeners: new_listeners,
318 attributes: new_attributes,
304 attributes: new_attributes,
319 children: new_children,
305 children: new_children,
320− } = new_element_node;
306+ namespace: _,
307+ }),
321− let ElementNode {
308+ Node::Element(ElementNode {
322 tag_name: old_tag_name,
309 tag_name: old_tag_name,
323 listeners: old_listeners,
310 listeners: old_listeners,
324 attributes: old_attributes,
311 attributes: old_attributes,
325 children: old_children,
312 children: old_children,
326− } = old_element_node;
313+ namespace: _,
314+ }),
315+ ) => {
327 debug!(" updating an element");
316 debug!(" updating an element");
328 if new_tag_name != old_tag_name {
317 if new_tag_name != old_tag_name {
329 debug!(" different tag names; creating new element and replacing old element");
318 debug!(" different tag names; creating new element and replacing old element");
@@ -475,32 +464,13 @@ impl VdomInnerExclusive {
475 listeners,
464 listeners,
476 attributes,
465 attributes,
477 children,
466 children,
467+ namespace,
478 }) => {
468 }) => {
469+ if let Some(namespace) = namespace {
470+ self.change_list.emit_create_element_ns(tag_name, namespace);
471+ } else {
479− self.change_list.emit_create_element(tag_name);
472+ self.change_list.emit_create_element(tag_name);
480− for l in listeners {
481− unsafe {
482− registry.add(l);
483− }
484− self.change_list.emit_new_event_listener(l);
485 }
473 }
486− for attr in attributes {
487− self.change_list.emit_set_attribute(&attr.name, &attr.value);
488− }
489− for child in children {
490− self.create(registry, child.clone());
491− self.change_list.emit_append_child();
492− }
493− }
494− Node::NamespacedElement(
495− namepsace,
496− ElementNode {
497− tag_name,
498− listeners,
499− attributes,
500− children,
501− },
502− ) => {
503− self.change_list.emit_create_element_ns(tag_name, namepsace);
504 for l in listeners {
474 for l in listeners {
505 unsafe {
475 unsafe {
506 registry.add(l);
476 registry.add(l);
@@ -508,7 +478,7 @@ impl VdomInnerExclusive {
508 self.change_list.emit_new_event_listener(l);
478 self.change_list.emit_new_event_listener(l);
509 }
479 }
510 for attr in attributes {
480 for attr in attributes {
511− if attr.name == "xmlns" {
481+ if namespace.is_none() || attr.name == "xmlns" {
512 self.change_list.emit_set_attribute(&attr.name, &attr.value);
482 self.change_list.emit_set_attribute(&attr.name, &attr.value);
513 } else {
483 } else {
514 self.change_list
484 self.change_list