WIP: move to static props

This commit is contained in:
Jonathan Kelley committed 2021-05-31 18:55:56 -04:00
1 parent c5089ba3c5
commit c1fd848f89
37 files changed
+1014 -339

No files matched your search

+30 -17
View File
@@ -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))});
}
}
+17 -6
View File
@@ -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 {
+17 -14
View File
@@ -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)
}
});
}
+72
View File
@@ -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);
}
}
+20 -4
View File
@@ -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)
}