forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhtml_node.rs
More file actions
86 lines (78 loc) · 2.52 KB
/
html_node.rs
File metadata and controls
86 lines (78 loc) · 2.52 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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,
}
}
}