This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

yew_macro/html_tree/
html_node.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{quote, quote_spanned, ToTokens};
3use syn::buffer::Cursor;
4use syn::parse::{Parse, ParseStream, Result};
5use syn::spanned::Spanned;
6use syn::{Expr, Lit};
7
8use super::ToNodeIterator;
9use crate::stringify::Stringify;
10use crate::PeekValue;
11
12pub enum HtmlNode {
13    Literal(Box<Lit>),
14    Expression(Box<Expr>),
15}
16
17impl Parse for HtmlNode {
18    fn parse(input: ParseStream) -> Result<Self> {
19        let node = if HtmlNode::peek(input.cursor()).is_some() {
20            let lit = input.parse()?;
21            match lit {
22                Lit::ByteStr(lit) => {
23                    return Err(syn::Error::new(
24                        lit.span(),
25                        "byte-strings can't be converted to HTML text
26                         note: remove the `b` prefix or convert this to a `String`",
27                    ))
28                }
29                Lit::Verbatim(lit) => {
30                    return Err(syn::Error::new(lit.span(), "unsupported literal"))
31                }
32                _ => (),
33            }
34            HtmlNode::Literal(Box::new(lit))
35        } else {
36            HtmlNode::Expression(Box::new(input.parse()?))
37        };
38
39        Ok(node)
40    }
41}
42
43impl PeekValue<()> for HtmlNode {
44    fn peek(cursor: Cursor) -> Option<()> {
45        cursor.literal().map(|_| ()).or_else(|| {
46            let (ident, _) = cursor.ident()?;
47            match ident.to_string().as_str() {
48                "true" | "false" => Some(()),
49                _ => None,
50            }
51        })
52    }
53}
54
55impl ToTokens for HtmlNode {
56    fn to_tokens(&self, tokens: &mut TokenStream) {
57        tokens.extend(match &self {
58            HtmlNode::Literal(lit) => {
59                let sr = lit.stringify();
60                quote_spanned! {lit.span()=> ::yew::virtual_dom::VText::new(#sr) }
61            }
62            HtmlNode::Expression(expr) => quote! {#expr},
63        });
64    }
65}
66
67impl ToNodeIterator for HtmlNode {
68    fn to_node_iterator_stream(&self) -> Option<TokenStream> {
69        match self {
70            HtmlNode::Literal(_) => None,
71            HtmlNode::Expression(expr) => {
72                // NodeSeq turns both Into<T> and Vec<Into<T>> into IntoIterator<Item = T>
73                Some(quote_spanned! {expr.span().resolved_at(Span::call_site())=>
74                    ::std::convert::Into::<::yew::utils::NodeSeq<_, _>>::into(#expr)
75                })
76            }
77        }
78    }
79}