|
@@ -14,8 +14,8 @@ use syn::{
|
|
|
pub struct Element<const AS: HTML_OR_RSX> {
|
|
|
name: Ident,
|
|
|
key: Option<AttrType>,
|
|
|
- attributes: Vec<ElementAttr>,
|
|
|
- listeners: Vec<ElementAttr>,
|
|
|
+ attributes: Vec<ElementAttr<AS>>,
|
|
|
+ listeners: Vec<ElementAttr<AS>>,
|
|
|
children: Vec<BodyNode<AS>>,
|
|
|
is_static: bool,
|
|
|
}
|
|
@@ -28,8 +28,8 @@ impl Parse for Element<AS_RSX> {
|
|
|
let content: ParseBuffer;
|
|
|
syn::braced!(content in stream);
|
|
|
|
|
|
- let mut attributes: Vec<ElementAttr> = vec![];
|
|
|
- let mut listeners: Vec<ElementAttr> = vec![];
|
|
|
+ let mut attributes: Vec<ElementAttr<AS_RSX>> = vec![];
|
|
|
+ let mut listeners: Vec<ElementAttr<AS_RSX>> = vec![];
|
|
|
let mut children: Vec<BodyNode<AS_RSX>> = vec![];
|
|
|
let mut key = None;
|
|
|
|
|
@@ -40,7 +40,7 @@ impl Parse for Element<AS_RSX> {
|
|
|
}
|
|
|
|
|
|
if content.peek(Ident) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
|
|
|
- parse_element_body(
|
|
|
+ parse_rsx_element_field(
|
|
|
&content,
|
|
|
&mut attributes,
|
|
|
&mut listeners,
|
|
@@ -71,45 +71,114 @@ impl Parse for Element<AS_RSX> {
|
|
|
|
|
|
impl Parse for Element<AS_HTML> {
|
|
|
fn parse(stream: ParseStream) -> Result<Self> {
|
|
|
- let name = Ident::parse(stream)?;
|
|
|
+ let l_tok = stream.parse::<Token![<]>()?;
|
|
|
+ let el_name = Ident::parse(stream)?;
|
|
|
|
|
|
// parse the guts
|
|
|
- let content: ParseBuffer;
|
|
|
- syn::braced!(content in stream);
|
|
|
+ // let content: ParseBuffer;
|
|
|
+ // syn::braced!(content in stream);
|
|
|
|
|
|
- let mut attributes: Vec<ElementAttr> = vec![];
|
|
|
- let mut listeners: Vec<ElementAttr> = vec![];
|
|
|
+ let mut attributes: Vec<ElementAttr<AS_HTML>> = vec![];
|
|
|
+ let mut listeners: Vec<ElementAttr<AS_HTML>> = vec![];
|
|
|
let mut children: Vec<BodyNode<AS_HTML>> = vec![];
|
|
|
let mut key = None;
|
|
|
|
|
|
- 'parsing: loop {
|
|
|
- // [1] Break if empty
|
|
|
- if content.is_empty() {
|
|
|
- break 'parsing;
|
|
|
+ // loop {
|
|
|
+ // if stream.peek(Token![>]) {
|
|
|
+ // break;
|
|
|
+ // } else {
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ while !stream.peek(Token![>]) {
|
|
|
+ // self-closing
|
|
|
+ if stream.peek(Token![/]) {
|
|
|
+ stream.parse::<Token![/]>()?;
|
|
|
+ stream.parse::<Token![>]>()?;
|
|
|
+
|
|
|
+ return Ok(Self {
|
|
|
+ name: el_name,
|
|
|
+ key: None,
|
|
|
+ attributes,
|
|
|
+ is_static: false,
|
|
|
+ listeners,
|
|
|
+ children,
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- if content.peek(Ident) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
|
|
|
- parse_element_body(
|
|
|
- &content,
|
|
|
- &mut attributes,
|
|
|
- &mut listeners,
|
|
|
- &mut key,
|
|
|
- name.clone(),
|
|
|
- )?;
|
|
|
+ let name = Ident::parse_any(stream)?;
|
|
|
+ let name_str = name.to_string();
|
|
|
+ stream.parse::<Token![=]>()?;
|
|
|
+ if name_str.starts_with("on") {
|
|
|
+ todo!()
|
|
|
} else {
|
|
|
- children.push(content.parse::<BodyNode<AS_HTML>>()?);
|
|
|
- }
|
|
|
+ match name_str.as_str() {
|
|
|
+ "style" => todo!(),
|
|
|
+ "key" => todo!(),
|
|
|
+ "classes" => todo!(),
|
|
|
+ "namespace" => todo!(),
|
|
|
+ "ref" => todo!(),
|
|
|
+ _ => {
|
|
|
+ let ty = if stream.peek(LitStr) {
|
|
|
+ let rawtext = stream.parse::<LitStr>().unwrap();
|
|
|
+ AttrType::BumpText(rawtext)
|
|
|
+ } else {
|
|
|
+ let toks = stream.parse::<Expr>()?;
|
|
|
+ AttrType::FieldTokens(toks)
|
|
|
+ };
|
|
|
+ attributes.push(ElementAttr {
|
|
|
+ element_name: el_name.clone(),
|
|
|
+ name,
|
|
|
+ value: ty,
|
|
|
+ namespace: None,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // if stream.peek(LitStr) {
|
|
|
|
|
|
- // consume comma if it exists
|
|
|
- // we don't actually care if there *are* commas after elements/text
|
|
|
- if content.peek(Token![,]) {
|
|
|
- let _ = content.parse::<Token![,]>();
|
|
|
- }
|
|
|
+ // } else {
|
|
|
+ // }
|
|
|
+ // if name_str.starts_with("on") {}
|
|
|
+
|
|
|
+ // attributes.push(stream.parse()?);
|
|
|
+ }
|
|
|
+ stream.parse::<Token![>]>()?;
|
|
|
+
|
|
|
+ // closing element
|
|
|
+ stream.parse::<Token![<]>()?;
|
|
|
+ stream.parse::<Token![/]>()?;
|
|
|
+ let close = Ident::parse_any(stream)?;
|
|
|
+ if close.to_string() != el_name.to_string() {
|
|
|
+ return Err(Error::new_spanned(
|
|
|
+ close,
|
|
|
+ "closing element does not match opening",
|
|
|
+ ));
|
|
|
}
|
|
|
+ stream.parse::<Token![>]>()?;
|
|
|
+ // 'parsing: loop {
|
|
|
+ // // if stream.peek(Token![>]) {}
|
|
|
+
|
|
|
+ // // // [1] Break if empty
|
|
|
+ // // if content.is_empty() {
|
|
|
+ // // break 'parsing;
|
|
|
+ // // }
|
|
|
+
|
|
|
+ // if content.peek(Ident) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
|
|
|
+ // parse_element_body(
|
|
|
+ // &content,
|
|
|
+ // &mut attributes,
|
|
|
+ // &mut listeners,
|
|
|
+ // &mut key,
|
|
|
+ // name.clone(),
|
|
|
+ // )?;
|
|
|
+ // } else {
|
|
|
+ // children.push(stream.parse::<BodyNode<AS_HTML>>()?);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
|
|
|
Ok(Self {
|
|
|
key,
|
|
|
- name,
|
|
|
+ name: el_name,
|
|
|
attributes,
|
|
|
children,
|
|
|
listeners,
|
|
@@ -140,7 +209,7 @@ impl<const AS: HTML_OR_RSX> ToTokens for Element<AS> {
|
|
|
/// =======================================
|
|
|
/// Parse a VElement's Attributes
|
|
|
/// =======================================
|
|
|
-struct ElementAttr {
|
|
|
+struct ElementAttr<const AS: HTML_OR_RSX> {
|
|
|
element_name: Ident,
|
|
|
name: Ident,
|
|
|
value: AttrType,
|
|
@@ -157,14 +226,14 @@ enum AttrType {
|
|
|
// We parse attributes and dump them into the attribute vec
|
|
|
// This is because some tags might be namespaced (IE style)
|
|
|
// These dedicated tags produce multiple name-spaced attributes
|
|
|
-fn parse_element_body(
|
|
|
+fn parse_rsx_element_field(
|
|
|
stream: ParseStream,
|
|
|
- attrs: &mut Vec<ElementAttr>,
|
|
|
- listeners: &mut Vec<ElementAttr>,
|
|
|
+ attrs: &mut Vec<ElementAttr<AS_RSX>>,
|
|
|
+ listeners: &mut Vec<ElementAttr<AS_RSX>>,
|
|
|
key: &mut Option<AttrType>,
|
|
|
element_name: Ident,
|
|
|
) -> Result<()> {
|
|
|
- let mut name = Ident::parse_any(stream)?;
|
|
|
+ let name = Ident::parse_any(stream)?;
|
|
|
let name_str = name.to_string();
|
|
|
stream.parse::<Token![:]>()?;
|
|
|
|
|
@@ -199,7 +268,8 @@ fn parse_element_body(
|
|
|
|
|
|
let ty: AttrType = match name_str.as_str() {
|
|
|
// short circuit early if style is using the special syntax
|
|
|
- "style" if stream.peek(token::Brace) => {
|
|
|
+ "style" if stream.peek(Token![:]) => {
|
|
|
+ stream.parse::<Token![:]>().unwrap();
|
|
|
let inner;
|
|
|
syn::braced!(inner in stream);
|
|
|
|
|
@@ -267,7 +337,7 @@ fn parse_element_body(
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
-impl ToTokens for ElementAttr {
|
|
|
+impl<const AS: HTML_OR_RSX> ToTokens for ElementAttr<AS> {
|
|
|
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
|
|
let el_name = &self.element_name;
|
|
|
let name_str = self.name.to_string();
|