From 4b8e9f4a125b9d55439d919786f33d9d5df234e8 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 2 Mar 2021 00:14:28 -0500 Subject: [PATCH] Feat: wowza got it all working --- Cargo.toml | 8 +- README.md | 9 +- packages/cli/Cargo.toml | 2 +- packages/core-macro/examples/rsxt.rs | 147 +++++++++++++++++++++------ packages/core-macro/src/rsxt.rs | 100 ++++++++++-------- packages/core/examples/rsx_usage.rs | 32 +++--- packages/web/Cargo.toml | 2 +- packages/web/examples/rsxt.rs | 38 +++++++ 8 files changed, 233 insertions(+), 105 deletions(-) create mode 100644 packages/web/examples/rsxt.rs diff --git a/Cargo.toml b/Cargo.toml index 4cdcc9688..44d161884 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [workspace] members = [ # Built-in + "packages/dioxus", "packages/core-macro", - # "packages/dioxus", - # "packages/core", + "packages/core", + "packages/web", # "packages/router", # "packages/ssr", # "packages/webview", - # "packages/web", # "packages/livehost", # "packages/vscode-ext", # "packages/recoil", @@ -16,7 +16,7 @@ members = [ # TODO @Jon, share the validation code # "packages/web", # "packages/hooks", - # "packages/cli", + "packages/cli", # "examples", # "packages/html-macro", # "packages/html-macro-2", diff --git a/README.md b/README.md index 2e366e76a..488af04fc 100644 --- a/README.md +++ b/README.md @@ -16,24 +16,21 @@ static Example: FC<()> = |ctx, props| { ctx.render(rsx! { div { h1 { "Hello, {selection}" } - button { "?", onclick: move |_| set_selection("world!") } - button { "?", onclick: move |_| set_selection("Dioxus 🎉") } + button { "?", onclick: {move |_| set_selection("world!")}} + button { "?", onclick: {move |_| set_selection("Dioxus 🎉")}} } }) }; - ``` Dioxus can be used to deliver webapps, desktop apps, static pages, liveview apps, Android apps, iOS Apps, and more. At its core, Dioxus is entirely renderer agnostic and has great documentation for creating new renderers for any platform. - - ### **Things you'll love ❤️:** - Minimal boilerplate - Ergonomic lifetime design for props and state management - Simple build, test, and deploy - "Dioxus Designer" for instant component reloading -- Support for html! and rsx! templating +- Support for html! **and** rsx! templating - SSR, WASM, desktop, and mobile support diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 0c629513e..500950fe0 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -12,7 +12,7 @@ description = "CLI tool for developing, testing, and publishing Dioxus apps" thiserror = "1.0.23" log = "0.4.13" fern = { version = "0.6.0", features = ["colored"] } -wasm-bindgen-cli-support = "0.2.70" +wasm-bindgen-cli-support = "0.2.71" anyhow = "1.0.38" argh = "0.1.4" serde = "1.0.120" diff --git a/packages/core-macro/examples/rsxt.rs b/packages/core-macro/examples/rsxt.rs index 843ef1c2c..72c1465c9 100644 --- a/packages/core-macro/examples/rsxt.rs +++ b/packages/core-macro/examples/rsxt.rs @@ -1,46 +1,127 @@ use dioxus_core_macro::rsx; +pub mod dioxus { + pub mod builder { + pub struct Builder; + + struct AttrVal; + + impl Into for &'static str { + fn into(self) -> AttrVal { + todo!() + } + } + + impl Into for String { + fn into(self) -> AttrVal { + todo!() + } + } + // impl From for AttrVal { + // fn from(_: T) -> Self { + // todo!() + // } + // } + + impl Builder { + // fn attr(mut self, key: &str, value: impl Into) -> Self { + pub fn attr(mut self, key: &str, value: T) -> Self { + Self + } + + pub fn on(mut self, key: &str, value: T) -> Self { + Self + } + + pub fn finish(mut self) { + // Self + } + } + + pub struct Bump; + pub fn div(bump: &Bump) -> Builder { + todo!() + } + pub fn h1(bump: &Bump) -> Builder { + todo!() + } + pub fn h2(bump: &Bump) -> Builder { + todo!() + } + } +} +use dioxus::builder::Bump; pub fn main() { // render(rsx! { - // _ {} + // div { // we can actually support just a list of nodes too + // h1 {"Hello Dioxus"} + // p {"This is a beautful app you're building"} + // section { + // "custom section to the rescue", + // class: "abc123" + // } + // span { + // class: "abc123" + // "Try backwards too." + // "Anything goes!" + // "As long as it's within the rules" + // {0..10.map(|f| rsx!{ + // div { + // h3 {"totally okay to drop in iterators and expressions"} + // p {"however, debug information is lost"} + // } + // })} + // } + // span { + // "Feel free" + // class: "abc123" + // "To mix to your heart's content" + // } + // span { class: "some-very-long-and-tedious-class-name-is-now-separated" + // "Very ergonomic" + // } + // span { "Innovative design 🛠" + // class: "some-very-long-and-tedious-class-name-is-now-separated" + // } + // } // }); let g = String::from("asd"); - let lazy = rsx! { - div { - a: "asd", - a: "asd", - a: "asd", - a: "asd", - a: "asd", - a: {rsx!{ h1 {"hello world"} }}, // include - a: {g}, - b: {1 + 2}, - onclick: {move |_| { - println!("hello world!") - }}, - div { - a: "asd" - div { - div { - div { + // let lazy = rsx! { + // div { + // a: "asd", + // a: "asd", + // a: "asd", + // a: "asd", + // a: "asd", + // // a: {rsx!{ h1 {"hello world"} }}, // include + // a: {&g}, + // b: {1 + 2}, + // onclick: {move |e: ()| { + // println!("hello world!") + // }}, + // div { + // a: "asd" + // div { + // div { + // div { - } - } - } - } - h1 { + // } + // } + // } + // } + // h1 { - } - h2 { - "child" - } - "Childnode" - } - }; + // } + // h2 { + // "child" + // } + // "Childnode" + // } + // }; - render(lazy); + // render(lazy); } -fn render(f: impl Fn(())) {} +fn render(f: impl Fn(&dioxus::builder::Bump)) {} diff --git a/packages/core-macro/src/rsxt.rs b/packages/core-macro/src/rsxt.rs index c42d10c50..a8edd99a1 100644 --- a/packages/core-macro/src/rsxt.rs +++ b/packages/core-macro/src/rsxt.rs @@ -49,7 +49,9 @@ use { // ============================================== // Parse any stream coming from the rsx! macro // ============================================== -pub struct RsxRender {} +pub struct RsxRender { + el: Element, +} impl Parse for RsxRender { fn parse(input: ParseStream) -> Result { @@ -57,20 +59,22 @@ impl Parse for RsxRender { // can only accept one root per component // fragments can be used as // _ { content } - let g: Element = input.parse()?; - Ok(Self {}) + let el: Element = input.parse()?; + Ok(Self { el }) } } impl ToTokens for RsxRender { - fn to_tokens(&self, tokens: &mut TokenStream2) { - let new_toks = quote! { - move |_| { - todo!() - } + fn to_tokens(&self, out_tokens: &mut TokenStream2) { + let new_toks = ToToksCtx::new(&self.el).to_token_stream(); + // let new_toks = ToToksCtx::new(&self.kind).to_token_stream(); + + // create a lazy tree that accepts a bump allocator + let final_tokens = quote! { + move |bump: &Bump| { #new_toks } }; - new_toks.to_tokens(tokens) + final_tokens.to_tokens(out_tokens); } } @@ -100,14 +104,23 @@ impl ToTokens for ToToksCtx<&Node> { impl Parse for Node { fn parse(s: ParseStream) -> Result { let fork = s.fork(); - if let Ok(text) = fork.parse::() { + + let ret = if let Ok(text) = fork.parse::() { s.advance_to(&fork); - return Ok(Self::Text(text)); + Ok(Self::Text(text)) } else if let Ok(el) = s.parse::() { - return Ok(Self::Element(el)); + Ok(Self::Element(el)) } else { + // TODO: Span information panic!("Not a valid child node"); + }; + + // consume comma if it exists + // we don't actually care if there *are* commas after elements/text + if s.peek(Token![,]) { + let _ = s.parse::(); } + ret } } @@ -125,37 +138,37 @@ struct Element { impl ToTokens for ToToksCtx<&Element> { fn to_tokens(&self, tokens: &mut TokenStream2) { - todo!() + // todo!() // // let ctx = self.ctx; - // let name = &self.inner.name; - // tokens.append_all(quote! { - // dioxus::builder::#name(bump) - // }); - // for attr in self.inner.attrs.iter() { - // self.recurse(attr).to_tokens(tokens); - // } - // match &self.inner.children { - // MaybeExpr::Expr(expr) => tokens.append_all(quote! { - // .children(#expr) - // }), - // MaybeExpr::Literal(nodes) => { - // let mut children = nodes.iter(); - // if let Some(child) = children.next() { - // let mut inner_toks = TokenStream2::new(); - // self.recurse(child).to_tokens(&mut inner_toks); - // while let Some(child) = children.next() { - // quote!(,).to_tokens(&mut inner_toks); - // self.recurse(child).to_tokens(&mut inner_toks); - // } - // tokens.append_all(quote! { - // .children([#inner_toks]) - // }); - // } - // } - // } - // tokens.append_all(quote! { - // .finish() - // }); + let name = &self.inner.name; + tokens.append_all(quote! { + dioxus::builder::#name(bump) + }); + for attr in self.inner.attrs.iter() { + self.recurse(attr).to_tokens(tokens); + } + match &self.inner.children { + MaybeExpr::Expr(expr) => tokens.append_all(quote! { + .children(#expr) + }), + MaybeExpr::Literal(nodes) => { + let mut children = nodes.iter(); + if let Some(child) = children.next() { + let mut inner_toks = TokenStream2::new(); + self.recurse(child).to_tokens(&mut inner_toks); + while let Some(child) = children.next() { + quote!(,).to_tokens(&mut inner_toks); + self.recurse(child).to_tokens(&mut inner_toks); + } + tokens.append_all(quote! { + .children([#inner_toks]) + }); + } + } + } + tokens.append_all(quote! { + .finish() + }); } } @@ -214,7 +227,8 @@ impl Parse for Element { panic!("Entry is not an attr or element\n {}", content) } - let children = MaybeExpr::Literal(Vec::new()); + let children = MaybeExpr::Literal(children); + // let children = MaybeExpr::Literal(Vec::new()); // // Contents of an element can either be a brace (in which case we just copy verbatim), or a // // sequence of nodes. // let children = if s.peek(token::Brace) { diff --git a/packages/core/examples/rsx_usage.rs b/packages/core/examples/rsx_usage.rs index b1ff32d18..1ab197bf8 100644 --- a/packages/core/examples/rsx_usage.rs +++ b/packages/core/examples/rsx_usage.rs @@ -12,23 +12,21 @@ struct ButtonProps<'a> { fn CustomButton(ctx: Context, props: ButtonProps) -> DomTree { let onfocus = move |evt: ()| log::debug!("Focused"); - ctx.render(rsx! { - button { - // ..props.attrs, - class: "abc123", - style: { a: 2, b: 3, c: 4 }, - onclick: move |evt| { - log::info("hello world"); - }, - onfocus, - onhover: props.onhover, - - Custom1 { a: 123 } - Custom2 { a: 456, "abc", h1 {"1"}, h2 {"2"} } - Custom3 { a: "sometext goes here" } - Custom4 { onclick: |evt| log::info("click") } - } - }) + todo!() + // ctx.render(rsx! { + // // button { + // // // ..props.attrs, + // // class: "abc123", + // // // style: { a: 2, b: 3, c: 4 }, + // // onclick: {move |evt| { + // // log::info("hello world"); + // // }}, + // // // Custom1 { a: 123 } + // // // Custom2 { a: 456, "abc", h1 {"1"}, h2 {"2"} } + // // // Custom3 { a: "sometext goes here" } + // // // Custom4 { onclick: |evt| log::info("click") } + // // } + // }) } // h1 { diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index f383e2312..b5f276723 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT/Apache-2.0" [dependencies] dioxus-core = { path = "../core", version = "0.1.2" } js-sys = "0.3" -wasm-bindgen = "0.2.69" +wasm-bindgen = "0.2.71" # wasm-bindgen = "0.2.70" lazy_static = "1.4.0" wasm-bindgen-futures = "0.4.20" diff --git a/packages/web/examples/rsxt.rs b/packages/web/examples/rsxt.rs new file mode 100644 index 000000000..e327198c1 --- /dev/null +++ b/packages/web/examples/rsxt.rs @@ -0,0 +1,38 @@ +use bumpalo::Bump; +use dioxus::prelude::*; +use dioxus_core as dioxus; +use dioxus_web::WebsysRenderer; + +fn main() { + wasm_logger::init(wasm_logger::Config::new(log::Level::Debug)); + console_error_panic_hook::set_once(); + + wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example)) +} + +static Example: FC<()> = |ctx, props| { + let (name, set_name) = use_state(&ctx, || "...?"); + + ctx.render(rsx! { + div { class: "py-12 px-4 text-center w-full max-w-2xl mx-auto" + span { "Dioxus Example: Jack and Jill", + class: "text-sm font-semibold" + } + h2 { "Hello, {name}", + class: "text-5xl mt-2 mb-6 leading-tight font-semibold font-heading" + } + div { + button { "Jack!" + class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow" + onclick: {move |_| set_name("jack")} + } + + button { "Jill!" + class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow" + onclick: {move |_| set_name("jill")} + onclick: {move |_| set_name("jill")} + } + } + } + }) +};