Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify and change children logic in the html macro #1275

Merged
merged 16 commits into from
Jun 9, 2020
Merged
2 changes: 1 addition & 1 deletion examples/nested_list/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl ListItem {

html! {
<div class="list-item-details">
{ self.props.children.render() }
{ self.props.children.clone() }
</div>
}
}
Expand Down
4 changes: 2 additions & 2 deletions yew-functional/src/use_context_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::any::TypeId;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::{iter, mem};
use yew::html::{AnyScope, Renderable, Scope};
use yew::html::{AnyScope, Scope};
use yew::{Children, Component, ComponentLink, Html, Properties};

type ConsumerCallback<T> = Box<dyn Fn(Rc<T>)>;
Expand Down Expand Up @@ -83,7 +83,7 @@ impl<T: Clone + 'static> Component for ContextProvider<T> {
}

fn view(&self) -> Html {
self.children.render()
self.children.clone().into_iter().collect::<Html>()
}
}

Expand Down
4 changes: 2 additions & 2 deletions yew-functional/tests/use_context_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

extern crate yew;

use yew::{html, App, Children, Html, Properties, Renderable};
use yew::{html, App, Children, Html, Properties};
use yew_functional::{
use_context, use_effect, use_ref, use_state, ContextProvider, FunctionComponent,
FunctionProvider,
Expand Down Expand Up @@ -198,7 +198,7 @@ fn use_context_update_works() {
<div id=props.id.clone()>
{ format!("total: {}", counter.borrow()) }
</div>
{ props.children.render() }
{ props.children.clone() }
</>
};
}
Expand Down
13 changes: 13 additions & 0 deletions yew-macro/src/html_tree/html_block.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::html_iterable::HtmlIterable;
use super::html_node::HtmlNode;
use super::ToNodeIterator;
use crate::PeekValue;
use proc_macro2::Delimiter;
use quote::{quote, quote_spanned, ToTokens};
Expand Down Expand Up @@ -49,3 +50,15 @@ impl ToTokens for HtmlBlock {
tokens.extend(quote_spanned! {brace.span=> #new_tokens});
}
}

impl ToNodeIterator for HtmlBlock {
fn to_node_iterator_stream(&self) -> Option<proc_macro2::TokenStream> {
let HtmlBlock { content, brace } = self;
let new_tokens = match content {
BlockContent::Iterable(iterable) => iterable.to_node_iterator_stream(),
BlockContent::Node(node) => node.to_node_iterator_stream(),
}?;

Some(quote_spanned! {brace.span=> #new_tokens})
}
}
18 changes: 7 additions & 11 deletions yew-macro/src/html_tree/html_component.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::HtmlChildrenTree;
use super::HtmlProp;
use super::HtmlPropSuffix;
use super::HtmlTreeNested;
use crate::PeekValue;
use boolinator::Boolinator;
use proc_macro2::Span;
Expand All @@ -19,7 +19,7 @@ use syn::{
pub struct HtmlComponent {
ty: Type,
props: Props,
children: Vec<HtmlTreeNested>,
children: HtmlChildrenTree,
}

impl PeekValue<()> for HtmlComponent {
Expand Down Expand Up @@ -48,11 +48,11 @@ impl Parse for HtmlComponent {
return Ok(HtmlComponent {
ty: open.ty,
props: open.props,
children: Vec::new(),
children: HtmlChildrenTree::new(),
});
}

let mut children: Vec<HtmlTreeNested> = vec![];
let mut children = HtmlChildrenTree::new();
loop {
if input.is_empty() {
return Err(syn::Error::new_spanned(
Expand All @@ -66,7 +66,7 @@ impl Parse for HtmlComponent {
}
}

children.push(input.parse()?);
children.parse_child(input)?;
}

input.parse::<HtmlComponentClose>()?;
Expand Down Expand Up @@ -110,11 +110,7 @@ impl ToTokens for HtmlComponent {

let set_children = if !children.is_empty() {
quote! {
.children(::yew::html::ChildrenRenderer::new({
let mut v = ::std::vec::Vec::new();
#(v.extend(::yew::utils::NodeSeq::from(#children));)*
v
}))
.children(::yew::html::ChildrenRenderer::new(#children))
}
} else {
quote! {}
Expand Down Expand Up @@ -157,7 +153,7 @@ impl ToTokens for HtmlComponent {
let key = if let Some(key) = props.key() {
quote_spanned! { key.span()=> Some(#key) }
} else {
quote! {None }
quote! {None}
};

tokens.extend(quote! {{
Expand Down
22 changes: 15 additions & 7 deletions yew-macro/src/html_tree/html_iterable.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::ToNodeIterator;
use crate::PeekValue;
use boolinator::Boolinator;
use proc_macro2::TokenStream;
Expand Down Expand Up @@ -39,14 +40,21 @@ impl Parse for HtmlIterable {
impl ToTokens for HtmlIterable {
fn to_tokens(&self, tokens: &mut TokenStream) {
let expr = &self.0;
let new_tokens = quote_spanned! {expr.span()=> {
let mut __yew_vlist = ::yew::virtual_dom::VList::default();
for __yew_node in #expr {
__yew_vlist.add_child(__yew_node.into());
}
::yew::virtual_dom::VNode::from(__yew_vlist)
}};
let new_tokens = quote_spanned! {expr.span()=>
::std::iter::Iterator::collect::<::yew::virtual_dom::VNode>(::std::iter::IntoIterator::into_iter(#expr))
};

tokens.extend(new_tokens);
}
}

impl ToNodeIterator for HtmlIterable {
fn to_node_iterator_stream(&self) -> Option<TokenStream> {
let Self(expr) = self;
// #expr can return anything that implements IntoIterator<Item=Into<T>>
// so we generate some extra code to turn it into IntoIterator<Item=T>
Some(quote_spanned! {expr.span()=>
::std::iter::Iterator::map(::std::iter::IntoIterator::into_iter(#expr), |n| n.into())
})
}
}
26 changes: 15 additions & 11 deletions yew-macro/src/html_tree/html_list.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::HtmlTree;
use super::HtmlChildrenTree;
use crate::html_tree::{HtmlProp, HtmlPropSuffix};
use crate::PeekValue;
use boolinator::Boolinator;
Expand All @@ -10,8 +10,17 @@ use syn::spanned::Spanned;
use syn::{Expr, Token};

pub struct HtmlList {
pub children: Vec<HtmlTree>,
pub key: Option<Expr>,
children: HtmlChildrenTree,
key: Option<Expr>,
}

impl HtmlList {
pub fn empty() -> Self {
Self {
children: HtmlChildrenTree::new(),
key: None,
}
}
}

impl PeekValue<()> for HtmlList {
Expand Down Expand Up @@ -42,9 +51,9 @@ impl Parse for HtmlList {
));
}

let mut children: Vec<HtmlTree> = vec![];
let mut children = HtmlChildrenTree::new();
while HtmlListClose::peek(input.cursor()).is_none() {
children.push(input.parse()?);
children.parse_child(input)?;
}

input.parse::<HtmlListClose>()?;
Expand All @@ -66,12 +75,7 @@ impl ToTokens for HtmlList {
};
tokens.extend(quote! {
::yew::virtual_dom::VNode::VList(
::yew::virtual_dom::VList::new_with_children({
let mut v = ::std::vec::Vec::new();
#(v.extend(::yew::utils::NodeSeq::from(#children));)*
v
},
#key)
::yew::virtual_dom::VList::new_with_children(#children, #key)
)
});
}
Expand Down
42 changes: 22 additions & 20 deletions yew-macro/src/html_tree/html_node.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use super::ToNodeIterator;
use crate::PeekValue;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::buffer::Cursor;
use syn::parse::{Parse, ParseStream, Result};
use syn::spanned::Spanned;
use syn::Expr;
use syn::Lit;
use syn::{Expr, Lit};

pub struct HtmlNode(Node);
pub enum HtmlNode {
Literal(Box<Lit>),
Expression(Box<Expr>),
}

impl Parse for HtmlNode {
fn parse(input: ParseStream) -> Result<Self> {
Expand All @@ -17,12 +20,12 @@ impl Parse for HtmlNode {
Lit::Str(_) | Lit::Char(_) | Lit::Int(_) | Lit::Float(_) | Lit::Bool(_) => {}
_ => return Err(syn::Error::new(lit.span(), "unsupported type")),
}
Node::Literal(Box::new(lit))
HtmlNode::Literal(Box::new(lit))
} else {
Node::Expression(Box::new(input.parse()?))
HtmlNode::Expression(Box::new(input.parse()?))
};

Ok(HtmlNode(node))
Ok(node)
}
}

Expand All @@ -40,22 +43,21 @@ impl PeekValue<()> for HtmlNode {

impl ToTokens for HtmlNode {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
tokens.extend(match &self {
HtmlNode::Literal(lit) => quote! {#lit},
HtmlNode::Expression(expr) => quote_spanned! {expr.span()=> {#expr}},
});
}
}

impl ToTokens for Node {
fn to_tokens(&self, tokens: &mut TokenStream) {
let node_token = match &self {
Node::Literal(lit) => quote! {#lit},
Node::Expression(expr) => quote_spanned! {expr.span()=> {#expr} },
};

tokens.extend(node_token);
impl ToNodeIterator for HtmlNode {
fn to_node_iterator_stream(&self) -> Option<TokenStream> {
match self {
HtmlNode::Literal(_) => None,
HtmlNode::Expression(expr) => {
// NodeSeq turns both Into<T> and Vec<Into<T>> into IntoIterator<Item = T>
Some(quote_spanned! {expr.span()=> ::yew::utils::NodeSeq::from(#expr)})
}
}
}
}

enum Node {
Literal(Box<Lit>),
Expression(Box<Expr>),
}
12 changes: 6 additions & 6 deletions yew-macro/src/html_tree/html_tag/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod tag_attributes;

use super::HtmlChildrenTree;
use super::HtmlDashedName;
use super::HtmlProp as TagAttribute;
use super::HtmlPropSuffix as TagSuffix;
use super::HtmlTree;
use crate::{non_capitalized_ascii, Peek, PeekValue};
use boolinator::Boolinator;
use proc_macro2::{Delimiter, Span};
Expand All @@ -18,7 +18,7 @@ use tag_attributes::{ClassesForm, TagAttributes};
pub struct HtmlTag {
tag_name: TagName,
attributes: TagAttributes,
children: Vec<HtmlTree>,
children: HtmlChildrenTree,
}

impl PeekValue<()> for HtmlTag {
Expand Down Expand Up @@ -47,7 +47,7 @@ impl Parse for HtmlTag {
return Ok(HtmlTag {
tag_name: open.tag_name,
attributes: open.attributes,
children: Vec::new(),
children: HtmlChildrenTree::new(),
});
}

Expand All @@ -66,7 +66,7 @@ impl Parse for HtmlTag {
}

let open_key = open.tag_name.get_key();
let mut children: Vec<HtmlTree> = vec![];
let mut children = HtmlChildrenTree::new();
loop {
if input.is_empty() {
return Err(syn::Error::new_spanned(
Expand All @@ -80,7 +80,7 @@ impl Parse for HtmlTag {
}
}

children.push(input.parse()?);
children.parse_child(input)?;
}

input.parse::<HtmlTagClose>()?;
Expand Down Expand Up @@ -244,7 +244,7 @@ impl ToTokens for HtmlTag {
#(#set_key)*
#vtag.add_attributes(vec![#(#attr_pairs),*]);
#vtag.add_listeners(vec![#(::std::rc::Rc::new(#listeners)),*]);
#vtag.add_children(vec![#(#children),*]);
#vtag.add_children(#children);
#dyn_tag_runtime_checks
::yew::virtual_dom::VNode::from(#vtag)
}});
Expand Down
Loading