mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
87 lines
2.5 KiB
Rust
87 lines
2.5 KiB
Rust
use proc_macro2::{Span, TokenStream};
|
|
use quote::{quote, quote_spanned, ToTokens};
|
|
use syn::buffer::Cursor;
|
|
use syn::parse::{Parse, ParseStream, Result};
|
|
use syn::spanned::Spanned;
|
|
use syn::Lit;
|
|
|
|
use super::ToNodeIterator;
|
|
use crate::stringify::Stringify;
|
|
use crate::PeekValue;
|
|
|
|
pub enum HtmlNode {
|
|
Literal(Box<Lit>),
|
|
Expression(Box<TokenStream>),
|
|
}
|
|
|
|
impl Parse for HtmlNode {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let node = if HtmlNode::peek(input.cursor()).is_some() {
|
|
let lit = input.parse()?;
|
|
match lit {
|
|
Lit::ByteStr(lit) => {
|
|
return Err(syn::Error::new(
|
|
lit.span(),
|
|
"byte-strings can't be converted to HTML text
|
|
note: remove the `b` prefix or convert this to a `String`",
|
|
))
|
|
}
|
|
Lit::Verbatim(lit) => {
|
|
return Err(syn::Error::new(lit.span(), "unsupported literal"))
|
|
}
|
|
_ => (),
|
|
}
|
|
HtmlNode::Literal(Box::new(lit))
|
|
} else {
|
|
HtmlNode::Expression(Box::new(input.parse()?))
|
|
};
|
|
|
|
Ok(node)
|
|
}
|
|
}
|
|
|
|
impl PeekValue<()> for HtmlNode {
|
|
fn peek(cursor: Cursor) -> Option<()> {
|
|
cursor.literal().map(|_| ()).or_else(|| {
|
|
let (ident, _) = cursor.ident()?;
|
|
match ident.to_string().as_str() {
|
|
"true" | "false" => Some(()),
|
|
_ => None,
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
impl ToTokens for HtmlNode {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.extend(match &self {
|
|
HtmlNode::Literal(lit) => {
|
|
let sr = lit.stringify();
|
|
quote_spanned! {lit.span()=> ::yew::virtual_dom::VText::new(#sr) }
|
|
}
|
|
HtmlNode::Expression(expr) => quote! {#expr},
|
|
});
|
|
}
|
|
}
|
|
|
|
impl ToNodeIterator for HtmlNode {
|
|
fn to_node_iterator_stream(&self) -> Option<TokenStream> {
|
|
match self {
|
|
Self::Literal(_) => None,
|
|
Self::Expression(expr) => {
|
|
// NodeSeq turns both Into<T> and Vec<Into<T>> into IntoIterator<Item = T>
|
|
Some(quote_spanned! {expr.span().resolved_at(Span::call_site())=>
|
|
::std::convert::Into::<::yew::utils::NodeSeq<_, _>>::into(#expr)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
fn is_singular(&self) -> bool {
|
|
match self {
|
|
Self::Literal(_) => true,
|
|
Self::Expression(_) => false,
|
|
}
|
|
}
|
|
}
|