WIP: move to static props
This commit is contained in:
1 parent
c5089ba3c5
commit
c1fd848f89
37 files changed
+1014
-339
No files matched your search
@@ -13,6 +13,8 @@
|
||||
//!
|
||||
//!
|
||||
|
||||
use crate::util::is_valid_svg_tag;
|
||||
|
||||
use {
|
||||
proc_macro::TokenStream,
|
||||
proc_macro2::{Span, TokenStream as TokenStream2},
|
||||
@@ -32,13 +34,17 @@ pub struct HtmlRender {
|
||||
}
|
||||
|
||||
impl Parse for HtmlRender {
|
||||
fn parse(s: ParseStream) -> Result<Self> {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(LitStr) {
|
||||
return input.parse::<LitStr>()?.parse::<HtmlRender>();
|
||||
}
|
||||
|
||||
// let ctx: Ident = s.parse()?;
|
||||
// s.parse::<Token![,]>()?;
|
||||
// if elements are in an array, return a bumpalo::collections::Vec rather than a Node.
|
||||
let kind = if s.peek(token::Bracket) {
|
||||
let kind = if input.peek(token::Bracket) {
|
||||
let nodes_toks;
|
||||
syn::bracketed!(nodes_toks in s);
|
||||
syn::bracketed!(nodes_toks in input);
|
||||
let mut nodes: Vec<MaybeExpr<Node>> = vec![nodes_toks.parse()?];
|
||||
while nodes_toks.peek(Token![,]) {
|
||||
nodes_toks.parse::<Token![,]>()?;
|
||||
@@ -46,7 +52,7 @@ impl Parse for HtmlRender {
|
||||
}
|
||||
NodeOrList::List(NodeList(nodes))
|
||||
} else {
|
||||
NodeOrList::Node(s.parse()?)
|
||||
NodeOrList::Node(input.parse()?)
|
||||
};
|
||||
Ok(HtmlRender { kind })
|
||||
}
|
||||
@@ -147,13 +153,20 @@ struct Element {
|
||||
impl ToTokens for ToToksCtx<&Element> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
// let ctx = self.ctx;
|
||||
let _name = &self.inner.name;
|
||||
let name = &self.inner.name.to_string();
|
||||
tokens.append_all(quote! {
|
||||
dioxus::builder::ElementBuilder::new(ctx, "#name")
|
||||
dioxus::builder::ElementBuilder::new(ctx, #name)
|
||||
});
|
||||
for attr in self.inner.attrs.iter() {
|
||||
self.recurse(attr).to_tokens(tokens);
|
||||
}
|
||||
|
||||
if is_valid_svg_tag(name) {
|
||||
tokens.append_all(quote! {
|
||||
.namespace(Some("http://www.w3.org/2000/svg"))
|
||||
});
|
||||
}
|
||||
|
||||
match &self.inner.children {
|
||||
MaybeExpr::Expr(expr) => tokens.append_all(quote! {
|
||||
.children(#expr)
|
||||
@@ -229,6 +242,7 @@ impl Parse for Element {
|
||||
));
|
||||
}
|
||||
s.parse::<Token![>]>()?;
|
||||
|
||||
Ok(Self {
|
||||
name,
|
||||
attrs,
|
||||
@@ -297,9 +311,15 @@ impl ToTokens for ToToksCtx<&Attr> {
|
||||
match &self.inner.ty {
|
||||
AttrType::Value(value) => {
|
||||
let value = self.recurse(value);
|
||||
tokens.append_all(quote! {
|
||||
.attr(#name, #value)
|
||||
});
|
||||
if name == "xmlns" {
|
||||
tokens.append_all(quote! {
|
||||
.namespace(Some(#value))
|
||||
});
|
||||
} else {
|
||||
tokens.append_all(quote! {
|
||||
.attr(#name, format_args_f!(#value))
|
||||
});
|
||||
}
|
||||
}
|
||||
AttrType::Event(event) => {
|
||||
tokens.append_all(quote! {
|
||||
@@ -334,14 +354,7 @@ impl ToTokens for ToToksCtx<&TextNode> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
let mut token_stream = TokenStream2::new();
|
||||
self.recurse(&self.inner.0).to_tokens(&mut token_stream);
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(bump);
|
||||
s.write_fmt(format_args_f!(#token_stream)).unwrap();
|
||||
dioxus::builder::text2(s)
|
||||
}
|
||||
});
|
||||
tokens.append_all(quote! {dioxus::builder::text3(bump, format_args_f!(#token_stream))});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ use proc_macro::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use syn::parse_macro_input;
|
||||
|
||||
mod fc;
|
||||
mod htm;
|
||||
mod ifmt;
|
||||
mod props;
|
||||
mod rsxt;
|
||||
mod util;
|
||||
pub(crate) mod fc;
|
||||
pub(crate) mod htm;
|
||||
pub(crate) mod ifmt;
|
||||
pub(crate) mod props;
|
||||
pub(crate) mod rsxt;
|
||||
pub(crate) mod rsxtemplate;
|
||||
pub(crate) mod util;
|
||||
|
||||
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
||||
/// We aim to keep functional parity with html templates.
|
||||
@@ -29,6 +30,16 @@ pub fn rsx(s: TokenStream) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
|
||||
/// We aim to keep functional parity with html templates.
|
||||
#[proc_macro]
|
||||
pub fn rsx_template(s: TokenStream) -> TokenStream {
|
||||
match syn::parse::<rsxtemplate::RsxTemplate>(s) {
|
||||
Err(e) => e.to_compile_error().into(),
|
||||
Ok(s) => s.to_token_stream().into(),
|
||||
}
|
||||
}
|
||||
|
||||
// #[proc_macro_attribute]
|
||||
// pub fn fc(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use syn::parse::{discouraged::Speculative, ParseBuffer};
|
||||
|
||||
use crate::util::is_valid_html_tag;
|
||||
use crate::util::is_valid_tag;
|
||||
|
||||
use {
|
||||
proc_macro::TokenStream,
|
||||
@@ -23,12 +23,16 @@ pub struct RsxRender {
|
||||
|
||||
impl Parse for RsxRender {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(LitStr) {
|
||||
return input.parse::<LitStr>()?.parse::<RsxRender>();
|
||||
}
|
||||
|
||||
// try to parse the first ident and comma
|
||||
let custom_context =
|
||||
if input.peek(Token![in]) && input.peek2(Ident) && input.peek3(Token![,]) {
|
||||
let _ = input.parse::<Token![in]>()?;
|
||||
let name = input.parse::<Ident>()?;
|
||||
if is_valid_html_tag(&name.to_string()) {
|
||||
if is_valid_tag(&name.to_string()) {
|
||||
return Err(Error::new(
|
||||
input.span(),
|
||||
"Custom context cannot be an html element name",
|
||||
@@ -114,7 +118,7 @@ impl Parse for AmbiguousElement {
|
||||
if let Ok(name) = input.fork().parse::<Ident>() {
|
||||
let name_str = name.to_string();
|
||||
|
||||
match is_valid_html_tag(&name_str) {
|
||||
match is_valid_tag(&name_str) {
|
||||
true => input
|
||||
.parse::<Element>()
|
||||
.map(|c| AmbiguousElement::Element(c)),
|
||||
@@ -134,6 +138,9 @@ impl Parse for AmbiguousElement {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if input.peek(LitStr) {
|
||||
panic!("it's actually a litstr");
|
||||
}
|
||||
Err(Error::new(input.span(), "Not a valid Html tag"))
|
||||
}
|
||||
}
|
||||
@@ -318,7 +325,7 @@ impl Parse for Element {
|
||||
//
|
||||
let name = Ident::parse(stream)?;
|
||||
|
||||
if !crate::util::is_valid_html_tag(&name.to_string()) {
|
||||
if !crate::util::is_valid_tag(&name.to_string()) {
|
||||
return Err(Error::new(name.span(), "Not a valid Html tag"));
|
||||
}
|
||||
|
||||
@@ -495,12 +502,7 @@ impl ToTokens for &ElementAttr {
|
||||
match &self.ty {
|
||||
AttrType::BumpText(value) => {
|
||||
tokens.append_all(quote! {
|
||||
.attr(#name, {
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(bump);
|
||||
s.write_fmt(format_args_f!(#value)).unwrap();
|
||||
s.into_bump_str()
|
||||
})
|
||||
.attr(#name, format_args_f!(#value))
|
||||
});
|
||||
}
|
||||
AttrType::Event(event) => {
|
||||
@@ -540,10 +542,11 @@ impl ToTokens for TextNode {
|
||||
let token_stream = &self.0.to_token_stream();
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(bump);
|
||||
s.write_fmt(format_args_f!(#token_stream)).unwrap();
|
||||
dioxus::builder::text2(s)
|
||||
// use bumpalo::core_alloc::fmt::Write;
|
||||
// let mut s = bumpalo::collections::String::new_in(bump);
|
||||
// s.write_fmt(format_args_f!(#token_stream)).unwrap();
|
||||
dioxus::builder::text3(bump, format_args_f!(#token_stream))
|
||||
// dioxus::builder::text2(s)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
use crate::{rsxt::RsxRender, util::is_valid_svg_tag};
|
||||
|
||||
use {
|
||||
proc_macro::TokenStream,
|
||||
proc_macro2::{Span, TokenStream as TokenStream2},
|
||||
quote::{quote, ToTokens, TokenStreamExt},
|
||||
syn::{
|
||||
ext::IdentExt,
|
||||
parse::{Parse, ParseStream},
|
||||
token, Error, Expr, ExprClosure, Ident, LitBool, LitStr, Path, Result, Token,
|
||||
},
|
||||
};
|
||||
|
||||
// ==============================================
|
||||
// Parse any stream coming from the html! macro
|
||||
// ==============================================
|
||||
pub struct RsxTemplate {
|
||||
inner: RsxRender,
|
||||
}
|
||||
|
||||
impl Parse for RsxTemplate {
|
||||
fn parse(s: ParseStream) -> Result<Self> {
|
||||
if s.peek(LitStr) {
|
||||
use std::str::FromStr;
|
||||
let lit = s.parse::<LitStr>()?;
|
||||
match lit.parse::<crate::rsxt::RsxRender>() {
|
||||
Ok(r) => Ok(Self { inner: r }),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
} else {
|
||||
panic!("Not a str lit")
|
||||
}
|
||||
// let t = s.parse::<LitStr>()?;
|
||||
|
||||
// let new_stream = TokenStream::from(t.to_s)
|
||||
|
||||
// let ctx: Ident = s.parse()?;
|
||||
// s.parse::<Token![,]>()?;
|
||||
// if elements are in an array, return a bumpalo::collections::Vec rather than a Node.
|
||||
// let kind = if s.peek(token::Bracket) {
|
||||
// let nodes_toks;
|
||||
// syn::bracketed!(nodes_toks in s);
|
||||
// let mut nodes: Vec<MaybeExpr<Node>> = vec![nodes_toks.parse()?];
|
||||
// while nodes_toks.peek(Token![,]) {
|
||||
// nodes_toks.parse::<Token![,]>()?;
|
||||
// nodes.push(nodes_toks.parse()?);
|
||||
// }
|
||||
// NodeOrList::List(NodeList(nodes))
|
||||
// } else {
|
||||
// NodeOrList::Node(s.parse()?)
|
||||
// };
|
||||
// Ok(HtmlRender { kind })
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for RsxTemplate {
|
||||
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
|
||||
self.inner.to_tokens(out_tokens);
|
||||
// let new_toks = ToToksCtx::new(&self.kind).to_token_stream();
|
||||
|
||||
// // create a lazy tree that accepts a bump allocator
|
||||
// let final_tokens = quote! {
|
||||
// dioxus::prelude::LazyNodes::new(move |ctx| {
|
||||
// let bump = &ctx.bump();
|
||||
|
||||
// #new_toks
|
||||
// })
|
||||
// };
|
||||
|
||||
// final_tokens.to_tokens(out_tokens);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::hash_set::HashSet;
|
||||
|
||||
static VALID_TAGS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
||||
/// rsx! and html! macros support the html namespace as well as svg namespace
|
||||
static HTML_TAGS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
||||
[
|
||||
"a",
|
||||
"abbr",
|
||||
@@ -117,9 +118,16 @@ static VALID_TAGS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
||||
"var",
|
||||
"video",
|
||||
"wbr",
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
});
|
||||
|
||||
static SVG_TAGS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
||||
[
|
||||
// SVTG
|
||||
"svg",
|
||||
"path",
|
||||
"svg", "path", "g",
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
@@ -135,6 +143,14 @@ static VALID_TAGS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
||||
///
|
||||
/// assert_eq!(is_valid_tag("random"), false);
|
||||
/// ```
|
||||
pub fn is_valid_tag(tag: &str) -> bool {
|
||||
is_valid_html_tag(tag) || is_valid_svg_tag(tag)
|
||||
}
|
||||
|
||||
pub fn is_valid_html_tag(tag: &str) -> bool {
|
||||
VALID_TAGS.contains(tag)
|
||||
HTML_TAGS.contains(tag)
|
||||
}
|
||||
|
||||
pub fn is_valid_svg_tag(tag: &str) -> bool {
|
||||
SVG_TAGS.contains(tag)
|
||||
}
|
||||
Reference in new issue
Block a user