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]
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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -5,7 +5,7 @@
// use dioxus::prelude::*;
fn main() {
dioxus::webview::launch(App);
dioxus::desktop::launch(App);
}
use dioxus::events::on::*;
+1 -1
View File
@@ -12,7 +12,7 @@
use dioxus::prelude::*;
fn main() {
dioxus::webview::launch(App);
dioxus::desktop::launch(App);
}
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>() {
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 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
View File
@@ -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
View File
@@ -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,5 +1,5 @@
[package]
name = "dioxus-html-namespace"
name = "dioxus-html"
version = "0.0.0"
edition = "2018"
File renamed without changes.
File renamed without changes.
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;