123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- //! Parse anything that has a pattern of < Ident, Bracket >
- //! ========================================================
- //!
- //! Whenever a `name {}` pattern emerges, we need to parse it into an element, a component, or a fragment.
- //! This feature must support:
- //! - Namepsaced/pathed components
- //! - Differentiating between built-in and custom elements
- use super::*;
- use proc_macro2::TokenStream as TokenStream2;
- use quote::ToTokens;
- use syn::{
- parse::{Parse, ParseStream},
- Error, Ident, LitStr, Result, Token,
- };
- pub enum AmbiguousElement<const AS: HTML_OR_RSX> {
- Element(Element<AS>),
- Component(Component<AS>),
- }
- impl Parse for AmbiguousElement<AS_RSX> {
- fn parse(input: ParseStream) -> Result<Self> {
- // Try to parse as an absolute path and immediately defer to the componetn
- if input.peek(Token![::]) {
- return input
- .parse::<Component<AS_RSX>>()
- .map(|c| AmbiguousElement::Component(c));
- }
- // If not an absolute path, then parse the ident and check if it's a valid tag
- if let Ok(pat) = input.fork().parse::<syn::Path>() {
- if pat.segments.len() > 1 {
- return input
- .parse::<Component<AS_RSX>>()
- .map(|c| AmbiguousElement::Component(c));
- }
- }
- if let Ok(name) = input.fork().parse::<Ident>() {
- let name_str = name.to_string();
- let first_char = name_str.chars().next().unwrap();
- if first_char.is_ascii_uppercase() {
- input
- .parse::<Component<AS_RSX>>()
- .map(|c| AmbiguousElement::Component(c))
- } else {
- input
- .parse::<Element<AS_RSX>>()
- .map(|c| AmbiguousElement::Element(c))
- }
- } else {
- if input.peek(LitStr) {
- panic!("it's actually a litstr");
- }
- Err(Error::new(input.span(), "Not a valid Html tag"))
- }
- }
- }
- impl Parse for AmbiguousElement<AS_HTML> {
- fn parse(input: ParseStream) -> Result<Self> {
- // Try to parse as an absolute path and immediately defer to the componetn
- if input.peek(Token![::]) {
- return input
- .parse::<Component<AS_HTML>>()
- .map(|c| AmbiguousElement::Component(c));
- }
- // If not an absolute path, then parse the ident and check if it's a valid tag
- if let Ok(pat) = input.fork().parse::<syn::Path>() {
- if pat.segments.len() > 1 {
- return input
- .parse::<Component<AS_HTML>>()
- .map(|c| AmbiguousElement::Component(c));
- }
- }
- if let Ok(name) = input.fork().parse::<Ident>() {
- let name_str = name.to_string();
- let first_char = name_str.chars().next().unwrap();
- if first_char.is_ascii_uppercase() {
- input
- .parse::<Component<AS_HTML>>()
- .map(|c| AmbiguousElement::Component(c))
- } else {
- input
- .parse::<Element<AS_HTML>>()
- .map(|c| AmbiguousElement::Element(c))
- }
- } else {
- if input.peek(LitStr) {
- panic!("it's actually a litstr");
- }
- Err(Error::new(input.span(), "Not a valid Html tag"))
- }
- }
- }
- impl<const AS: HTML_OR_RSX> ToTokens for AmbiguousElement<AS> {
- fn to_tokens(&self, tokens: &mut TokenStream2) {
- match self {
- AmbiguousElement::Element(el) => el.to_tokens(tokens),
- AmbiguousElement::Component(comp) => comp.to_tokens(tokens),
- }
- }
- }
|