text_node.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #[cfg(feature = "hot_reload")]
  2. use dioxus_core::TemplateNode;
  3. use crate::{
  4. literal::{HotLiteral, HotLiteralType},
  5. location::DynIdx,
  6. IfmtInput,
  7. };
  8. use proc_macro2::{Span, TokenStream as TokenStream2};
  9. use quote::ToTokens;
  10. use quote::{quote, TokenStreamExt};
  11. use syn::Result;
  12. use syn::{
  13. parse::{Parse, ParseStream},
  14. LitStr,
  15. };
  16. #[derive(PartialEq, Eq, Clone, Debug, Hash)]
  17. pub struct TextNode {
  18. pub input: IfmtInput,
  19. pub hr_idx: DynIdx,
  20. pub dyn_idx: DynIdx,
  21. }
  22. impl Parse for TextNode {
  23. fn parse(input: ParseStream) -> Result<Self> {
  24. Ok(Self {
  25. input: input.parse()?,
  26. hr_idx: DynIdx::default(),
  27. dyn_idx: DynIdx::default(),
  28. })
  29. }
  30. }
  31. impl ToTokens for TextNode {
  32. fn to_tokens(&self, tokens: &mut TokenStream2) {
  33. let txt = &self.input;
  34. if txt.is_static() {
  35. tokens.append_all(quote! {
  36. dioxus_core::DynamicNode::Text(dioxus_core::VText::new(#txt.to_string()))
  37. })
  38. } else {
  39. // todo:
  40. // Use the RsxLiteral implementation to spit out a hotreloadable variant of this string
  41. // This is not super efficient since we're doing a bit of cloning
  42. let as_lit = HotLiteral {
  43. hr_idx: self.hr_idx.clone(),
  44. value: HotLiteralType::Fmted(txt.clone()),
  45. };
  46. tokens.append_all(quote! {
  47. dioxus_core::DynamicNode::Text(dioxus_core::VText::new( #as_lit ))
  48. })
  49. }
  50. }
  51. }
  52. impl TextNode {
  53. pub fn from_text(text: &str) -> Self {
  54. let ifmt = IfmtInput {
  55. source: LitStr::new(text, Span::call_site()),
  56. segments: vec![],
  57. };
  58. Self {
  59. input: ifmt,
  60. dyn_idx: Default::default(),
  61. hr_idx: Default::default(),
  62. }
  63. }
  64. pub fn is_static(&self) -> bool {
  65. self.input.is_static()
  66. }
  67. #[cfg(feature = "hot_reload")]
  68. pub fn to_template_node(&self) -> TemplateNode {
  69. use crate::intern;
  70. match self.is_static() {
  71. true => {
  72. let text = self.input.source.clone();
  73. let text = intern(text.value().as_str());
  74. TemplateNode::Text { text }
  75. }
  76. false => TemplateNode::Dynamic {
  77. id: self.dyn_idx.get(),
  78. },
  79. }
  80. }
  81. }
  82. #[cfg(test)]
  83. mod tests {
  84. use super::*;
  85. use crate::PrettyUnparse;
  86. #[test]
  87. fn parses() {
  88. let input = syn::parse2::<TextNode>(quote! { "hello world" }).unwrap();
  89. assert_eq!(input.input.source.value(), "hello world");
  90. }
  91. #[test]
  92. fn to_tokens_with_hr() {
  93. let lit = syn::parse2::<TextNode>(quote! { "hi {world1} {world2} {world3}" }).unwrap();
  94. println!("{}", lit.to_token_stream().pretty_unparse());
  95. }
  96. #[test]
  97. fn raw_str() {
  98. let input = syn::parse2::<TextNode>(quote! { r#"hello world"# }).unwrap();
  99. println!("{}", input.input.source.to_token_stream());
  100. assert_eq!(input.input.source.value(), "hello world");
  101. }
  102. }