1use crate::{literal::HotLiteral, location::DynIdx, HotReloadFormattedSegment, IfmtInput};
2use proc_macro2::{Span, TokenStream as TokenStream2};
3use quote::ToTokens;
4use quote::{quote, TokenStreamExt};
5use syn::Result;
6use syn::{
7 parse::{Parse, ParseStream},
8 LitStr,
9};
10
11#[derive(PartialEq, Eq, Clone, Debug, Hash)]
12pub struct TextNode {
13 pub input: HotReloadFormattedSegment,
14 pub dyn_idx: DynIdx,
15}
16
17impl Parse for TextNode {
18 fn parse(input: ParseStream) -> Result<Self> {
19 Ok(Self {
20 input: input.parse()?,
21 dyn_idx: DynIdx::default(),
22 })
23 }
24}
25
26impl ToTokens for TextNode {
27 fn to_tokens(&self, tokens: &mut TokenStream2) {
28 let txt = &self.input;
29
30 if txt.is_static() {
31 tokens.append_all(quote! {
32 dioxus_core::DynamicNode::Text(dioxus_core::VText::new(#txt.to_string()))
33 })
34 } else {
35 let as_lit = HotLiteral::Fmted(txt.clone());
39
40 tokens.append_all(quote! {
41 dioxus_core::DynamicNode::Text(dioxus_core::VText::new( #as_lit ))
42 })
43 }
44 }
45}
46
47impl TextNode {
48 pub fn from_text(text: &str) -> Self {
49 let ifmt = IfmtInput {
50 source: LitStr::new(text, Span::call_site()),
51 segments: vec![],
52 };
53 Self {
54 input: ifmt.into(),
55 dyn_idx: Default::default(),
56 }
57 }
58
59 pub fn is_static(&self) -> bool {
60 self.input.is_static()
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use prettier_please::PrettyUnparse;
68
69 #[test]
70 fn parses() {
71 let input = syn::parse2::<TextNode>(quote! { "hello world" }).unwrap();
72 assert_eq!(input.input.source.value(), "hello world");
73 }
74
75 #[test]
76 fn to_tokens_with_hr() {
77 let lit = syn::parse2::<TextNode>(quote! { "hi {world1} {world2} {world3}" }).unwrap();
78 println!("{}", lit.to_token_stream().pretty_unparse());
79 }
80
81 #[test]
82 fn raw_str() {
83 let input = syn::parse2::<TextNode>(quote! { r#"hello world"# }).unwrap();
84 println!("{}", input.input.source.to_token_stream());
85 assert_eq!(input.input.source.value(), "hello world");
86 }
87}