feat: enable arbitrary body in rsx! macro

This commit is contained in:
Jonathan Kelley committed 2021-07-07 18:17:00 -04:00
1 parent fd7933561f
commit 7aec40d57e
38 files changed
+142 -88

No files matched your search

+6 -4
View File
@@ -10,20 +10,22 @@ description = "Core functionality for Dioxus - a concurrent renderer-agnostic Vi
[dependencies] [dependencies]
dioxus-core = { path="./packages/core", version="0.1.0" } dioxus-core = { path="./packages/core", version="0.1.0" }
dioxus-core-macro = { path="./packages/core-macro", 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-web = { path="./packages/web", optional=true }
dioxus-webview = { path="./packages/webview", optional=true }
# dioxus-hooks = { path="./packages/hooks", version="0.0.0" } # dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
[features] [features]
default = ["ssr", "hooks", "router", "web", "core", "atoms"] default = ["ssr", "hooks", "router", "core", "atoms", "html", "web", "desktop"]
atoms = [] atoms = []
core = [] core = []
ssr = [] ssr = []
hooks = [] hooks = []
router = [] router = []
html = ["dioxus-html"]
web = ["dioxus-web"] web = ["dioxus-web"]
desktop = [] desktop = ["dioxus-webview"]
[profile.dev] [profile.dev]
@@ -44,7 +46,7 @@ surf = "2.2.0"
members = [ members = [
"packages/core-macro", "packages/core-macro",
"packages/core", "packages/core",
"packages/html-namespace", "packages/html",
"packages/web", "packages/web",
"packages/webview", "packages/webview",
# "packages/atoms", # "packages/atoms",
+1 -1
View File
@@ -3,7 +3,7 @@
use dioxus::events::on::MouseEvent; use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::*; use dioxus_web::*;
fn main() { fn main() {
+1 -1
View File
@@ -9,7 +9,7 @@
use dioxus::events::on::*; use dioxus::events::on::*;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
const STYLE: &str = include_str!("../../../examples/assets/calculator.css"); const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
+1 -1
View File
@@ -1,7 +1,7 @@
//! Basic example that renders a simple VNode to the browser. //! Basic example that renders a simple VNode to the browser.
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::*; use dioxus_web::*;
fn main() { fn main() {
+1 -1
View File
@@ -14,7 +14,7 @@
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
fn main() { fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace)); wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
+1 -1
View File
@@ -2,7 +2,7 @@ use std::rc::Rc;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
fn main() { fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug)); wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
+2 -2
View File
@@ -1,6 +1,6 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_html_namespace::*; use dioxus_html::*;
use dioxus_web::{dioxus::prelude::*, WebsysRenderer}; use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
fn main() { fn main() {
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus::{events::on::MouseEvent, prelude::*}; use dioxus::{events::on::MouseEvent, prelude::*};
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
fn main() { fn main() {
+1 -1
View File
@@ -1,7 +1,7 @@
//! Basic example that renders a simple VNode to the browser. //! Basic example that renders a simple VNode to the browser.
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::*; use dioxus_web::*;
fn main() { fn main() {
+1 -1
View File
@@ -12,7 +12,7 @@ use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
fn main() { fn main() {
+1 -1
View File
@@ -1,5 +1,5 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::prelude::*; use dioxus_web::prelude::*;
fn main() { fn main() {
+1 -1
View File
@@ -1,7 +1,7 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::{events::on::MouseEvent, prelude::*}; use dioxus_core::{events::on::MouseEvent, prelude::*};
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
fn main() { fn main() {
+1 -1
View File
@@ -1,7 +1,7 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
fn main() { fn main() {
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
fn main() { fn main() {
+1 -1
View File
@@ -3,7 +3,7 @@
use std::rc::Rc; use std::rc::Rc;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::*; use dioxus_web::*;
fn main() { fn main() {
+1 -1
View File
@@ -1,7 +1,7 @@
//! Basic example that renders a simple VNode to the browser. //! Basic example that renders a simple VNode to the browser.
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::*; use dioxus_web::*;
fn main() { fn main() {
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use std::collections::BTreeMap; use std::collections::BTreeMap;
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
fn main() { fn main() {
+1 -1
View File
@@ -1,6 +1,6 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
fn main() { fn main() {
+1 -1
View File
@@ -18,7 +18,7 @@
use dioxus::events::on::*; use dioxus::events::on::*;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
const STYLE: &str = include_str!("../../../examples/assets/calculator.css"); const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
+1 -1
View File
@@ -4,7 +4,7 @@ use std::rc::Rc;
use dioxus::{events::on::MouseEvent, prelude::*}; use dioxus::{events::on::MouseEvent, prelude::*};
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
fn main() { fn main() {
+1 -1
View File
@@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc};
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
static APP_STYLE: &'static str = include_str!("./todomvc/style.css"); static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
+1 -1
View File
@@ -1,5 +1,5 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::{prelude::*, WebsysRenderer}; use dioxus_web::{prelude::*, WebsysRenderer};
// mod filtertoggles; // mod filtertoggles;
+1 -1
View File
@@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc};
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_html_namespace as dioxus_elements; use dioxus_html as dioxus_elements;
use dioxus_web::WebsysRenderer; use dioxus_web::WebsysRenderer;
static APP_STYLE: &'static str = include_str!("./todomvc/style.css"); static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
+1 -1
View File
@@ -5,7 +5,7 @@
// use dioxus::prelude::*; // use dioxus::prelude::*;
fn main() { fn main() {
dioxus::webview::launch(App); dioxus::desktop::launch(App);
} }
use dioxus::events::on::*; use dioxus::events::on::*;
+1 -1
View File
@@ -12,7 +12,7 @@
use dioxus::prelude::*; use dioxus::prelude::*;
fn main() { fn main() {
dioxus::webview::launch(App); dioxus::desktop::launch(App);
} }
static App: FC<()> = |cx| { static App: FC<()> = |cx| {
+5
View File
@@ -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>() { if let Ok(name) = input.fork().parse::<Ident>() {
let name_str = name.to_string(); let name_str = name.to_string();
+57 -27
View File
@@ -45,27 +45,17 @@ impl Parse for Component {
let mut children: Vec<Node> = Vec::new(); let mut children: Vec<Node> = Vec::new();
let mut manual_props = None; let mut manual_props = None;
'parsing: loop { parse_component_body(
// [1] Break if empty &content,
if content.is_empty() { &BodyParseConfig {
break 'parsing; allow_children: true,
} allow_fields: true,
allow_manual_props: true,
if content.peek(Token![..]) { },
content.parse::<Token![..]>()?; &mut body,
manual_props = Some(content.parse::<Expr>()?); &mut children,
} else if content.peek(Ident) && content.peek2(Token![:]) { &mut manual_props,
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![,]>();
}
}
Ok(Self { Ok(Self {
name, 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 { impl ToTokens for Component {
fn to_tokens(&self, tokens: &mut TokenStream2) { fn to_tokens(&self, tokens: &mut TokenStream2) {
let name = &self.name; let name = &self.name;
@@ -135,12 +171,6 @@ impl ToTokens for Component {
let children = quote! { let children = quote! {
[ #( #childs ),* ] [ #( #childs ),* ]
}; };
// ChildrenList::new(__cx)
// #( .add_child(#childs) )*
// .finish()
// ChildrenList::new(__cx)
// #( .add_child(#childs) )*
// .finish()
tokens.append_all(quote! { tokens.append_all(quote! {
__cx.virtual_child( __cx.virtual_child(
+19 -9
View File
@@ -34,14 +34,14 @@ use syn::{
pub struct RsxRender { pub struct RsxRender {
custom_context: Option<Ident>, custom_context: Option<Ident>,
roots: Vec<AmbiguousElement>, roots: Vec<Node>,
} }
impl Parse for RsxRender { impl Parse for RsxRender {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
if input.peek(LitStr) { // if input.peek(LitStr) {
return input.parse::<LitStr>()?.parse::<RsxRender>(); // return input.parse::<LitStr>()?.parse::<RsxRender>();
} // }
// try to parse the first ident and comma // try to parse the first ident and comma
let custom_context = let custom_context =
@@ -61,13 +61,23 @@ impl Parse for RsxRender {
None None
}; };
let mut roots = Vec::new(); let mut body = Vec::new();
while !input.is_empty() { let mut children = Vec::new();
roots.push(input.parse::<AmbiguousElement>()?); 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 { Ok(Self {
roots, roots: children,
custom_context, custom_context,
}) })
} }
+12 -12
View File
@@ -16,18 +16,6 @@ pub enum Node {
RawExpr(Expr), 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 { impl Parse for Node {
fn parse(stream: ParseStream) -> Result<Self> { fn parse(stream: ParseStream) -> Result<Self> {
// Supposedly this approach is discouraged due to inability to return proper errors // 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 // Parse just plain text
// ======================================= // =======================================
@@ -1,5 +1,5 @@
[package] [package]
name = "dioxus-html-namespace" name = "dioxus-html"
version = "0.0.0" version = "0.0.0"
edition = "2018" edition = "2018"
File renamed without changes.
File renamed without changes.
+1 -1
View File
@@ -9,7 +9,7 @@ license = "MIT/Apache-2.0"
[dependencies] [dependencies]
dioxus-core = { path="../core", version="0.1.2" } dioxus-core = { path="../core", version="0.1.2" }
dioxus-html-namespace = { path="../html-namespace" } dioxus-html = { path="../html" }
js-sys = "0.3" js-sys = "0.3"
wasm-bindgen = { version="0.2.71", features=["enable-interning"] } wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
lazy_static = "1.4.0" lazy_static = "1.4.0"
+1 -3
View File
@@ -2,13 +2,11 @@
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::prelude::*; use dioxus_core::prelude::*;
use dioxus_core::serialize::DomEdits;
use dioxus_core::{ use dioxus_core::{
diff::RealDom, diff::RealDom,
prelude::ScopeIdx, serialize::DomEdits,
virtual_dom::{RealDomNode, VirtualDom}, virtual_dom::{RealDomNode, VirtualDom},
}; };
use serde::{Deserialize, Serialize};
use DomEdits::*; use DomEdits::*;
pub struct WebviewDom<'bump> { pub struct WebviewDom<'bump> {
+9 -3
View File
@@ -9,10 +9,16 @@ mod dom;
static HTML_CONTENT: &'static str = include_str!("./index.html"); static HTML_CONTENT: &'static str = include_str!("./index.html");
pub fn launch<T: Properties + 'static>( pub fn launch(
builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder, builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder,
props: T, root: FC<()>,
root: FC<T>, ) -> 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<()> { ) -> anyhow::Result<()> {
WebviewRenderer::run(root, props, builder) WebviewRenderer::run(root, props, builder)
} }
+4 -1
View File
@@ -169,7 +169,7 @@ pub mod prelude {
//! A glob import that includes helper types like FC, rsx!, html!, and required traits //! A glob import that includes helper types like FC, rsx!, html!, and required traits
pub use dioxus_core::prelude::*; pub use dioxus_core::prelude::*;
pub use dioxus_core_macro::fc; 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 mod builder {
// // pub use dioxus_core::builder::*; // // pub use dioxus_core::builder::*;
@@ -218,3 +218,6 @@ pub mod testing {
} }
#[cfg(feature = "atoms")] #[cfg(feature = "atoms")]
pub mod atoms {} pub mod atoms {}
#[cfg(feature = "desktop")]
pub use dioxus_webview as desktop;