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

Allow any type to be used as Children (take 2) #3289

Merged
merged 31 commits into from
Jun 11, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e8337e7
Partially copy useful implementation.
futursolo Jun 2, 2023
ea87cc2
Adjust conversion.
futursolo Jun 2, 2023
2fbb5c3
Temporary fix iterator.
futursolo Jun 2, 2023
5345edc
Add ToString implementation.
futursolo Jun 2, 2023
810cc91
Add Renderable trait.
futursolo Jun 3, 2023
8a4ca82
Make Macro tests pass.
futursolo Jun 3, 2023
22c7827
Add tests for render_prop as Children.
futursolo Jun 3, 2023
e10ce9d
Update benchmark and Children used in yew packages.
futursolo Jun 3, 2023
1214ff8
Selective suppress lints.
futursolo Jun 3, 2023
5595b5b
Rollback unintentional rollback.
futursolo Jun 3, 2023
e01b76b
Fix rustfmt.
futursolo Jun 3, 2023
262ca27
Remove unneeded implementation.
futursolo Jun 3, 2023
89657da
Update Comment.
futursolo Jun 3, 2023
5800a82
Rollback more changes.
futursolo Jun 3, 2023
d88fcdf
Rollback more changes.
futursolo Jun 3, 2023
907b057
Fix website.
futursolo Jun 3, 2023
1fef14d
Fix documentation tests.
futursolo Jun 3, 2023
256c5e4
Add prelude.
futursolo Jun 3, 2023
8def3ae
Fix test.
futursolo Jun 3, 2023
fd7e429
Blanket Implementation for &'_ T for Renderable types.
futursolo Jun 3, 2023
5707a72
Implement Renderable for &str.
futursolo Jun 3, 2023
6df8fff
Update signature.
futursolo Jun 3, 2023
068d1a4
Update children to Html in examples.
futursolo Jun 3, 2023
7be43a9
Remove unnecessary dereferencing.
futursolo Jun 3, 2023
a0a6580
Rollback nested_list example.
futursolo Jun 3, 2023
98207bf
Fix comment.
futursolo Jun 3, 2023
26ccc47
Convert to Pattern Matching.
futursolo Jun 10, 2023
f1e75dc
Add tracing issue.
futursolo Jun 10, 2023
7f74c96
Rename Renderable to ToHtml.
futursolo Jun 10, 2023
b63ff7b
Move ToHtml to yew::html.
futursolo Jun 10, 2023
b00667d
Convert more to match pattern.
futursolo Jun 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
325 changes: 124 additions & 201 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/contexts/src/msg_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub type MessageContext = UseReducerHandle<Message>;
#[derive(Properties, Debug, PartialEq)]
pub struct MessageProviderProps {
#[prop_or_default]
pub children: Children,
pub children: Html,
}

#[function_component]
Expand Down
6 changes: 6 additions & 0 deletions examples/function_todomvc/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ impl Filter {
}
}

impl Renderable for Filter {
fn to_html(&self) -> Html {
html! {<>{self.to_string()}</>}
}
}

pub enum Action {
Add(String),
Edit((usize, String)),
Expand Down
8 changes: 5 additions & 3 deletions examples/futures/src/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ pub fn render_markdown(src: &str) -> Html {
top = pre;
} else if let Tag::Table(aligns) = tag {
if let Some(top_children) = top.children_mut() {
for r in top_children.iter_mut() {
for r in top_children.to_vlist_mut().iter_mut() {
if let VNode::VTag(ref mut vtag) = r {
if let Some(vtag_children) = vtag.children_mut() {
for (i, c) in vtag_children.iter_mut().enumerate() {
for (i, c) in
vtag_children.to_vlist_mut().iter_mut().enumerate()
{
if let VNode::VTag(ref mut vtag) = c {
match aligns[i] {
Alignment::None => {}
Expand All @@ -73,7 +75,7 @@ pub fn render_markdown(src: &str) -> Html {
}
} else if let Tag::TableHead = tag {
if let Some(top_children) = top.children_mut() {
for c in top_children.iter_mut() {
for c in top_children.to_vlist_mut().iter_mut() {
if let VNode::VTag(ref mut vtag) = c {
// TODO
// vtag.tag = "th".into();
Expand Down
9 changes: 8 additions & 1 deletion examples/nested_list/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::fmt;
use std::ops::Deref;
use std::rc::Rc;

use yew::html::{Component, ImplicitClone, Scope};
use yew::html::{ImplicitClone, Scope};
use yew::prelude::*;

pub struct WeakComponentLink<COMP: Component>(Rc<RefCell<Option<Scope<COMP>>>>);

Expand Down Expand Up @@ -62,6 +63,12 @@ impl fmt::Display for Hovered {
}
}

impl Renderable for Hovered {
fn to_html(&self) -> yew::Html {
html! {<>{self.to_string()}</>}
}
}

fn main() {
wasm_logger::init(wasm_logger::Config::default());
yew::Renderer::<app::App>::new().render();
Expand Down
11 changes: 3 additions & 8 deletions examples/portals/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use wasm_bindgen::JsCast;
use web_sys::{Element, ShadowRootInit, ShadowRootMode};
use yew::{create_portal, html, Children, Component, Context, Html, NodeRef, Properties};
use yew::{create_portal, html, Component, Context, Html, NodeRef, Properties};

#[derive(Properties, PartialEq)]
pub struct ShadowDOMProps {
#[prop_or_default]
pub children: Children,
pub children: Html,
}

pub struct ShadowDOMHost {
Expand Down Expand Up @@ -50,12 +50,7 @@ impl Component for ShadowDOMHost {

fn view(&self, ctx: &Context<Self>) -> Html {
let contents = if let Some(ref inner_host) = self.inner_host {
create_portal(
html! {
{for ctx.props().children.iter()}
},
inner_host.clone(),
)
create_portal(ctx.props().children.clone(), inner_host.clone())
} else {
html! { <></> }
};
Expand Down
7 changes: 7 additions & 0 deletions examples/todomvc/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use serde_derive::{Deserialize, Serialize};
use strum_macros::{Display, EnumIter};
use yew::prelude::*;

#[derive(Debug, Serialize, Deserialize)]
pub struct State {
Expand Down Expand Up @@ -140,3 +141,9 @@ impl Filter {
}
}
}

impl Renderable for Filter {
fn to_html(&self) -> yew::Html {
html! { <>{self.to_string()}</> }
}
}
6 changes: 1 addition & 5 deletions packages/yew-macro/src/html_tree/html_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,7 @@ impl ToTokens for HtmlComponent {

let ty_span = ty.span().resolved_at(Span::call_site());
let props_ty = quote_spanned!(ty_span=> <#ty as ::yew::html::BaseComponent>::Properties);
let children_renderer = if children.is_empty() {
None
} else {
Some(quote! { ::yew::html::ChildrenRenderer::new(#children) })
};
let children_renderer = children.to_children_renderer_tokens();
let build_props = props.build_properties_tokens(&props_ty, children_renderer);
let key = props.special().wrap_key_attr();
let use_close_tag = close
Expand Down
18 changes: 9 additions & 9 deletions packages/yew-macro/src/html_tree/html_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,7 @@ impl ToTokens for HtmlElement {

// TODO: if none of the children have possibly None expressions or literals as keys, we can
// compute `VList.fully_keyed` at compile time.
let child_list = quote! {
::yew::virtual_dom::VList::with_children(
#children,
::std::option::Option::None,
)
};
let children = children.to_vnode_tokens();

tokens.extend(match &name {
TagName::Lit(dashedname) => {
Expand Down Expand Up @@ -370,7 +365,7 @@ impl ToTokens for HtmlElement {
#key,
#attributes,
#listeners,
#child_list,
#children,
),
)
}
Expand All @@ -392,6 +387,8 @@ impl ToTokens for HtmlElement {
let expr = &name.expr;
let vtag_name = Ident::new("__yew_vtag_name", expr.span());

let void_children = Ident::new("__yew_void_children", Span::mixed_site());

// handle special attribute value
let handle_value_attr = props.value.as_ref().map(|prop| {
let v = prop.value.optimize_literals();
Expand Down Expand Up @@ -455,7 +452,7 @@ impl ToTokens for HtmlElement {
#key,
#attributes,
#listeners,
#child_list,
#children,
);

#handle_value_attr
Expand All @@ -468,7 +465,10 @@ impl ToTokens for HtmlElement {
// For literal tags this is already done at compile-time.
//
// check void element
if !#vtag.children().is_empty() {
if !::std::matches!(
::yew::virtual_dom::VTag::children(&#vtag),
::std::option::Option::Some(::yew::virtual_dom::VNode::VList(ref #void_children)) if ::std::vec::Vec::is_empty(#void_children)
) {
::std::debug_assert!(
!::std::matches!(#vtag.tag().to_ascii_lowercase().as_str(),
"area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input"
Expand Down
58 changes: 58 additions & 0 deletions packages/yew-macro/src/html_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ use html_list::HtmlList;
use html_node::HtmlNode;
use tag::TagTokens;

use self::html_block::BlockContent;

pub enum HtmlType {
Block,
Component,
Expand Down Expand Up @@ -280,6 +282,62 @@ impl HtmlChildrenTree {

Ok(children)
}

pub fn to_children_renderer_tokens(&self) -> Option<TokenStream> {
if self.0.is_empty() {
return None;
}

if let [HtmlTree::Block(ref m)] = self.0[..] {
if let HtmlBlock {
content: BlockContent::Node(children),
..
} = m.as_ref()
{
return Some(quote! { #children });
}
}

if let [HtmlTree::Component(ref children)] = self.0[..] {
return Some(quote! { #children });
}

if let [HtmlTree::Element(ref children)] = self.0[..] {
return Some(quote! { #children });
}

Some(quote! { ::yew::html::ChildrenRenderer::new(#self) })
futursolo marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn to_vnode_tokens(&self) -> TokenStream {
if self.0.is_empty() {
return quote! {::std::default::Default::default() };
}

if let [HtmlTree::Block(ref m)] = self.0[..] {
if let HtmlBlock {
content: BlockContent::Node(children),
..
} = m.as_ref()
{
return quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) };
}
}

if let [HtmlTree::Component(ref children)] = self.0[..] {
return quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) };
}

if let [HtmlTree::Element(ref children)] = self.0[..] {
return quote! { ::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(#children) };
}

quote! {
::yew::html::IntoPropValue::<::yew::virtual_dom::VNode>::into_prop_value(
::yew::html::ChildrenRenderer::new(#self)
)
}
}
}

impl ToTokens for HtmlChildrenTree {
Expand Down
2 changes: 1 addition & 1 deletion packages/yew-macro/src/props/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl ComponentProps {
});
let set_children = children_renderer.map(|children| {
quote_spanned! {props_ty.span()=>
#ident.children = #children;
#ident.children = ::yew::html::IntoPropValue::into_prop_value(#children);
}
});
let init_base = quote_spanned! {expr.span().resolved_at(Span::call_site())=>
Expand Down
15 changes: 0 additions & 15 deletions packages/yew-macro/tests/html_macro/block-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ error[E0277]: `()` doesn't implement `std::fmt::Display`
= note: required because of the requirements on the impl of `Into<NodeSeq<(), VNode>>` for `()`
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: `()` doesn't implement `std::fmt::Display`
--> tests/html_macro/block-fail.rs:12:16
|
12 | <div>{ not_tree() }</div>
| ^^^^^^^^ `()` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required because of the requirements on the impl of `ToString` for `()`
= note: required because of the requirements on the impl of `From<()>` for `VNode`
= note: required because of the requirements on the impl of `Into<VNode>` for `()`
= note: 2 redundant requirements hidden
= note: required because of the requirements on the impl of `Into<NodeSeq<(), VNode>>` for `()`
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: `()` doesn't implement `std::fmt::Display`
--> tests/html_macro/block-fail.rs:15:17
|
Expand Down
Loading