Преглед изворни кода

feat: enable arbitrary body in rsx! macro

Jonathan Kelley пре 4 година
родитељ
комит
7aec40d57e
38 измењених фајлова са 142 додато и 88 уклоњено
  1. 6 4
      Cargo.toml
  2. 1 1
      examples/_examples/basic.rs
  3. 1 1
      examples/_examples/calculator.rs
  4. 1 1
      examples/_examples/children.rs
  5. 1 1
      examples/_examples/context.rs
  6. 1 1
      examples/_examples/deep.rs
  7. 2 2
      examples/_examples/demoday.rs
  8. 1 1
      examples/_examples/derive.rs
  9. 1 1
      examples/_examples/fragment.rs
  10. 1 1
      examples/_examples/framework_benchmark.rs
  11. 1 1
      examples/_examples/hello.rs
  12. 1 1
      examples/_examples/helloworld.rs
  13. 1 1
      examples/_examples/infer.rs
  14. 1 1
      examples/_examples/input.rs
  15. 1 1
      examples/_examples/jackjillrsx.rs
  16. 1 1
      examples/_examples/landingpage.rs
  17. 1 1
      examples/_examples/landingpage2.rs
  18. 1 1
      examples/_examples/list.rs
  19. 1 1
      examples/_examples/listy.rs
  20. 1 1
      examples/_examples/many.rs
  21. 1 1
      examples/_examples/model.rs
  22. 1 1
      examples/_examples/rsxt.rs
  23. 1 1
      examples/_examples/todomvc-nodeps.rs
  24. 1 1
      examples/_examples/todomvc/main.rs
  25. 1 1
      examples/_examples/todomvc_simple.rs
  26. 1 1
      examples/calculator.rs
  27. 1 1
      examples/webview.rs
  28. 5 0
      packages/core-macro/src/rsx/ambiguous.rs
  29. 57 27
      packages/core-macro/src/rsx/component.rs
  30. 19 9
      packages/core-macro/src/rsx/mod.rs
  31. 12 12
      packages/core-macro/src/rsx/node.rs
  32. 1 1
      packages/html/Cargo.toml
  33. 0 0
      packages/html/README.md
  34. 0 0
      packages/html/src/lib.rs
  35. 1 1
      packages/web/Cargo.toml
  36. 1 3
      packages/webview/src/dom.rs
  37. 9 3
      packages/webview/src/lib.rs
  38. 4 1
      src/lib.rs

+ 6 - 4
Cargo.toml

@@ -10,20 +10,22 @@ description = "Core functionality for Dioxus - a concurrent renderer-agnostic Vi
 [dependencies]
 dioxus-core = { path="./packages/core", version="0.1.0" }
 dioxus-core-macro = { path="./packages/core-macro", version="0.1.0" }
-dioxus-html-namespace = { path="./packages/html-namespace" }
+dioxus-html = { path="./packages/html", optional=true }
 dioxus-web = { path="./packages/web", optional=true }
+dioxus-webview = { path="./packages/webview", optional=true }
 # dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
 
 
 [features]
-default = ["ssr", "hooks", "router", "web", "core", "atoms"]
+default = ["ssr", "hooks", "router", "core", "atoms", "html", "web", "desktop"]
 atoms = []
 core = []
 ssr = []
 hooks = []
 router = []
+html = ["dioxus-html"]
 web = ["dioxus-web"]
-desktop = []
+desktop = ["dioxus-webview"]
 
 
 [profile.dev]
@@ -44,7 +46,7 @@ surf = "2.2.0"
 members = [
     "packages/core-macro",
     "packages/core",
-    "packages/html-namespace",
+    "packages/html",
     "packages/web",
     "packages/webview",
     # "packages/atoms",

+ 1 - 1
examples/_examples/basic.rs

@@ -3,7 +3,7 @@
 use dioxus::events::on::MouseEvent;
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 1
examples/_examples/calculator.rs

@@ -9,7 +9,7 @@
 use dioxus::events::on::*;
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 const STYLE: &str = include_str!("../../../examples/assets/calculator.css");

+ 1 - 1
examples/_examples/children.rs

@@ -1,7 +1,7 @@
 //! Basic example that renders a simple VNode to the browser.
 
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 1
examples/_examples/context.rs

@@ -14,7 +14,7 @@
 use dioxus_core::prelude::*;
 use dioxus_core as dioxus;
 use dioxus_web::WebsysRenderer;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));

+ 1 - 1
examples/_examples/deep.rs

@@ -2,7 +2,7 @@ use std::rc::Rc;
 
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));

+ 2 - 2
examples/_examples/demoday.rs

@@ -1,6 +1,6 @@
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
-use dioxus_html_namespace::*;
+use dioxus_html as dioxus_elements;
+use dioxus_html::*;
 use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
 
 fn main() {

+ 1 - 1
examples/_examples/derive.rs

@@ -1,6 +1,6 @@
 use dioxus::{events::on::MouseEvent, prelude::*};
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 1
examples/_examples/fragment.rs

@@ -1,7 +1,7 @@
 //! Basic example that renders a simple VNode to the browser.
 
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 1
examples/_examples/framework_benchmark.rs

@@ -12,7 +12,7 @@ use dioxus::events::on::MouseEvent;
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_web::WebsysRenderer;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 
 

+ 1 - 1
examples/_examples/hello.rs

@@ -1,6 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 1
examples/_examples/helloworld.rs

@@ -1,5 +1,5 @@
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::prelude::*;
 
 fn main() {

+ 1 - 1
examples/_examples/infer.rs

@@ -1,7 +1,7 @@
 use dioxus_core as dioxus;
 use dioxus_core::{events::on::MouseEvent, prelude::*};
 use dioxus_web::WebsysRenderer;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 
 fn main() {

+ 1 - 1
examples/_examples/input.rs

@@ -1,7 +1,7 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_web::WebsysRenderer;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 
 fn main() {

+ 1 - 1
examples/_examples/jackjillrsx.rs

@@ -1,6 +1,6 @@
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 1
examples/_examples/landingpage.rs

@@ -3,7 +3,7 @@
 use std::rc::Rc;
 
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 1
examples/_examples/landingpage2.rs

@@ -1,7 +1,7 @@
 //! Basic example that renders a simple VNode to the browser.
 
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 1
examples/_examples/list.rs

@@ -1,6 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 use std::collections::BTreeMap;
 

+ 1 - 1
examples/_examples/listy.rs

@@ -1,6 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 1
examples/_examples/many.rs

@@ -1,6 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 1
examples/_examples/model.rs

@@ -18,7 +18,7 @@
 use dioxus::events::on::*;
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 const STYLE: &str = include_str!("../../../examples/assets/calculator.css");

+ 1 - 1
examples/_examples/rsxt.rs

@@ -4,7 +4,7 @@ use std::rc::Rc;
 use dioxus::{events::on::MouseEvent, prelude::*};
 use dioxus_core as dioxus;
 use dioxus_web::WebsysRenderer;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 
 
 fn main() {

+ 1 - 1
examples/_examples/todomvc-nodeps.rs

@@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc};
 
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 static APP_STYLE: &'static str = include_str!("./todomvc/style.css");

+ 1 - 1
examples/_examples/todomvc/main.rs

@@ -1,5 +1,5 @@
 use dioxus_core as dioxus;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::{prelude::*, WebsysRenderer};
 
 // mod filtertoggles;

+ 1 - 1
examples/_examples/todomvc_simple.rs

@@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc};
 
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_html_namespace as dioxus_elements;
+use dioxus_html as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 static APP_STYLE: &'static str = include_str!("./todomvc/style.css");

+ 1 - 1
examples/calculator.rs

@@ -5,7 +5,7 @@
 // use dioxus::prelude::*;
 
 fn main() {
-    dioxus::webview::launch(App);
+    dioxus::desktop::launch(App);
 }
 
 use dioxus::events::on::*;

+ 1 - 1
examples/webview.rs

@@ -12,7 +12,7 @@
 use dioxus::prelude::*;
 
 fn main() {
-    dioxus::webview::launch(App);
+    dioxus::desktop::launch(App);
 }
 
 static App: FC<()> = |cx| {

+ 5 - 0
packages/core-macro/src/rsx/ambiguous.rs

@@ -39,6 +39,11 @@ impl Parse for AmbiguousElement {
             }
         }
 
+        // if input.peek(Ident) {
+        //     let name_str = input.fork().parse::<Ident>().unwrap().to_string();
+        // } else {
+        // }
+
         if let Ok(name) = input.fork().parse::<Ident>() {
             let name_str = name.to_string();
 

+ 57 - 27
packages/core-macro/src/rsx/component.rs

@@ -45,27 +45,17 @@ impl Parse for Component {
         let mut children: Vec<Node> = Vec::new();
         let mut manual_props = None;
 
-        'parsing: loop {
-            // [1] Break if empty
-            if content.is_empty() {
-                break 'parsing;
-            }
-
-            if content.peek(Token![..]) {
-                content.parse::<Token![..]>()?;
-                manual_props = Some(content.parse::<Expr>()?);
-            } else if content.peek(Ident) && content.peek2(Token![:]) {
-                body.push(content.parse::<ComponentField>()?);
-            } else {
-                children.push(content.parse::<Node>()?);
-            }
-
-            // consume comma if it exists
-            // we don't actually care if there *are* commas between attrs
-            if content.peek(Token![,]) {
-                let _ = content.parse::<Token![,]>();
-            }
-        }
+        parse_component_body(
+            &content,
+            &BodyParseConfig {
+                allow_children: true,
+                allow_fields: true,
+                allow_manual_props: true,
+            },
+            &mut body,
+            &mut children,
+            &mut manual_props,
+        )?;
 
         Ok(Self {
             name,
@@ -76,6 +66,52 @@ impl Parse for Component {
     }
 }
 
+pub struct BodyParseConfig {
+    pub allow_fields: bool,
+    pub allow_children: bool,
+    pub allow_manual_props: bool,
+}
+
+pub fn parse_component_body(
+    content: &ParseBuffer,
+    cfg: &BodyParseConfig,
+    body: &mut Vec<ComponentField>,
+    children: &mut Vec<Node>,
+    manual_props: &mut Option<Expr>,
+) -> Result<()> {
+    'parsing: loop {
+        // [1] Break if empty
+        if content.is_empty() {
+            break 'parsing;
+        }
+
+        if content.peek(Token![..]) {
+            if !cfg.allow_manual_props {
+                // toss an error
+            }
+            content.parse::<Token![..]>()?;
+            *manual_props = Some(content.parse::<Expr>()?);
+        } else if content.peek(Ident) && content.peek2(Token![:]) {
+            if !cfg.allow_fields {
+                // toss an error
+            }
+            body.push(content.parse::<ComponentField>()?);
+        } else {
+            if !cfg.allow_children {
+                // toss an error
+            }
+            children.push(content.parse::<Node>()?);
+        }
+
+        // consume comma if it exists
+        // we don't actually care if there *are* commas between attrs
+        if content.peek(Token![,]) {
+            let _ = content.parse::<Token![,]>();
+        }
+    }
+    Ok(())
+}
+
 impl ToTokens for Component {
     fn to_tokens(&self, tokens: &mut TokenStream2) {
         let name = &self.name;
@@ -135,12 +171,6 @@ impl ToTokens for Component {
         let children = quote! {
             [ #( #childs ),* ]
         };
-        // ChildrenList::new(__cx)
-        //     #( .add_child(#childs) )*
-        //     .finish()
-        // ChildrenList::new(__cx)
-        //     #( .add_child(#childs) )*
-        //     .finish()
 
         tokens.append_all(quote! {
             __cx.virtual_child(

+ 19 - 9
packages/core-macro/src/rsx/mod.rs

@@ -34,14 +34,14 @@ use syn::{
 
 pub struct RsxRender {
     custom_context: Option<Ident>,
-    roots: Vec<AmbiguousElement>,
+    roots: Vec<Node>,
 }
 
 impl Parse for RsxRender {
     fn parse(input: ParseStream) -> Result<Self> {
-        if input.peek(LitStr) {
-            return input.parse::<LitStr>()?.parse::<RsxRender>();
-        }
+        // if input.peek(LitStr) {
+        //     return input.parse::<LitStr>()?.parse::<RsxRender>();
+        // }
 
         // try to parse the first ident and comma
         let custom_context =
@@ -61,13 +61,23 @@ impl Parse for RsxRender {
                 None
             };
 
-        let mut roots = Vec::new();
-        while !input.is_empty() {
-            roots.push(input.parse::<AmbiguousElement>()?);
-        }
+        let mut body = Vec::new();
+        let mut children = Vec::new();
+        let mut manual_props = None;
+        parse_component_body(
+            input,
+            &BodyParseConfig {
+                allow_children: true,
+                allow_fields: false,
+                allow_manual_props: false,
+            },
+            &mut body,
+            &mut children,
+            &mut manual_props,
+        )?;
 
         Ok(Self {
-            roots,
+            roots: children,
             custom_context,
         })
     }

+ 12 - 12
packages/core-macro/src/rsx/node.rs

@@ -16,18 +16,6 @@ pub enum Node {
     RawExpr(Expr),
 }
 
-impl ToTokens for Node {
-    fn to_tokens(&self, tokens: &mut TokenStream2) {
-        match &self {
-            Node::Element(el) => el.to_tokens(tokens),
-            Node::Text(txt) => txt.to_tokens(tokens),
-            Node::RawExpr(exp) => tokens.append_all(quote! {
-                 __cx.fragment_from_iter(#exp)
-            }),
-        }
-    }
-}
-
 impl Parse for Node {
     fn parse(stream: ParseStream) -> Result<Self> {
         // Supposedly this approach is discouraged due to inability to return proper errors
@@ -47,6 +35,18 @@ impl Parse for Node {
     }
 }
 
+impl ToTokens for Node {
+    fn to_tokens(&self, tokens: &mut TokenStream2) {
+        match &self {
+            Node::Element(el) => el.to_tokens(tokens),
+            Node::Text(txt) => txt.to_tokens(tokens),
+            Node::RawExpr(exp) => tokens.append_all(quote! {
+                 __cx.fragment_from_iter(#exp)
+            }),
+        }
+    }
+}
+
 // =======================================
 // Parse just plain text
 // =======================================

+ 1 - 1
packages/html-namespace/Cargo.toml → packages/html/Cargo.toml

@@ -1,5 +1,5 @@
 [package]
-name = "dioxus-html-namespace"
+name = "dioxus-html"
 version = "0.0.0"
 edition = "2018"
 

+ 0 - 0
packages/html-namespace/README.md → packages/html/README.md


+ 0 - 0
packages/html-namespace/src/lib.rs → packages/html/src/lib.rs


+ 1 - 1
packages/web/Cargo.toml

@@ -9,7 +9,7 @@ license = "MIT/Apache-2.0"
 
 [dependencies]
 dioxus-core = { path="../core", version="0.1.2" }
-dioxus-html-namespace = { path="../html-namespace" }
+dioxus-html = { path="../html" }
 js-sys = "0.3"
 wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
 lazy_static = "1.4.0"

+ 1 - 3
packages/webview/src/dom.rs

@@ -2,13 +2,11 @@
 
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use dioxus_core::serialize::DomEdits;
 use dioxus_core::{
     diff::RealDom,
-    prelude::ScopeIdx,
+    serialize::DomEdits,
     virtual_dom::{RealDomNode, VirtualDom},
 };
-use serde::{Deserialize, Serialize};
 use DomEdits::*;
 
 pub struct WebviewDom<'bump> {

+ 9 - 3
packages/webview/src/lib.rs

@@ -9,10 +9,16 @@ mod dom;
 
 static HTML_CONTENT: &'static str = include_str!("./index.html");
 
-pub fn launch<T: Properties + 'static>(
+pub fn launch(
     builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder,
-    props: T,
-    root: FC<T>,
+    root: FC<()>,
+) -> anyhow::Result<()> {
+    launch_with_props(builder, (), root)
+}
+pub fn launch_with_props<P: Properties + 'static>(
+    builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder,
+    props: P,
+    root: FC<P>,
 ) -> anyhow::Result<()> {
     WebviewRenderer::run(root, props, builder)
 }

+ 4 - 1
src/lib.rs

@@ -169,7 +169,7 @@ pub mod prelude {
     //! A glob import that includes helper types like FC, rsx!, html!, and required traits
     pub use dioxus_core::prelude::*;
     pub use dioxus_core_macro::fc;
-    pub use dioxus_html_namespace as dioxus_elements;
+    pub use dioxus_html as dioxus_elements;
 }
 // pub mod builder {
 //     // pub use dioxus_core::builder::*;
@@ -218,3 +218,6 @@ pub mod testing {
 }
 #[cfg(feature = "atoms")]
 pub mod atoms {}
+
+#[cfg(feature = "desktop")]
+pub use dioxus_webview as desktop;