forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
/
html_node.rs
68 lines (62 loc) · 2.01 KB
/
html_node.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use super::ToNodeIterator;
use crate::stringify::Stringify;
use crate::PeekValue;
use proc_macro2::TokenStream;
use quote::{quote_spanned, ToTokens};
use syn::buffer::Cursor;
use syn::parse::{Parse, ParseStream, Result};
use syn::spanned::Spanned;
use syn::{Expr, Lit};
pub enum HtmlNode {
Literal(Box<Lit>),
Expression(Box<Expr>),
}
impl Parse for HtmlNode {
fn parse(input: ParseStream) -> Result<Self> {
let node = if HtmlNode::peek(input.cursor()).is_some() {
let lit: Lit = input.parse()?;
if matches!(lit, Lit::ByteStr(_) | Lit::Byte(_) | Lit::Verbatim(_)) {
return Err(syn::Error::new(lit.span(), "unsupported type"));
}
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_spanned! {expr.span()=> #expr},
});
}
}
impl ToNodeIterator for HtmlNode {
fn to_node_iterator_stream(&self) -> Option<TokenStream> {
match self {
HtmlNode::Literal(_) => None,
HtmlNode::Expression(expr) => {
// NodeSeq turns both Into<T> and Vec<Into<T>> into IntoIterator<Item = T>
Some(
quote_spanned! {expr.span()=> ::yew::utils::TryIntoNodeSeq::try_into_node_seq(#expr)?},
)
}
}
}
}