dioxus_document/elements/
mod.rs1#![doc = include_str!("../../docs/head.md")]
2
3use std::{cell::RefCell, collections::HashSet, rc::Rc};
4
5use dioxus_core::{
6 Attribute, DynamicNode, Element, RenderError, Runtime, ScopeId, Template, TemplateNode,
7};
8use dioxus_core_macro::*;
9
10mod link;
11pub use link::*;
12mod stylesheet;
13pub use stylesheet::*;
14mod meta;
15pub use meta::*;
16mod script;
17pub use script::*;
18mod style;
19pub use style::*;
20mod title;
21pub use title::*;
22
23#[allow(unused)]
25fn use_update_warning<T: PartialEq + Clone + 'static>(value: &T, name: &'static str) {
26 #[cfg(debug_assertions)]
27 {
28 use dioxus_core::use_hook;
29
30 let cloned_value = value.clone();
31 let initial = use_hook(move || value.clone());
32
33 if initial != cloned_value {
34 tracing::warn!("Changing the props of `{name}` is not supported ");
35 }
36 }
37}
38
39pub enum ExtractSingleTextNodeError<'a> {
41 RenderError(&'a RenderError),
43 NonTextNode,
45 NonTemplate,
47}
48
49impl ExtractSingleTextNodeError<'_> {
50 pub fn log(&self, component: &str) {
52 match self {
53 ExtractSingleTextNodeError::RenderError(err) => {
54 tracing::error!("Error while rendering {component}: {err}");
55 }
56 ExtractSingleTextNodeError::NonTextNode => {
57 tracing::error!(
58 "Error while rendering {component}: The children of {component} must be a single text node"
59 );
60 }
61 ExtractSingleTextNodeError::NonTemplate => {
62 tracing::error!(
63 "Error while rendering {component}: The children of {component} must be a single text node"
64 );
65 }
66 }
67 }
68}
69
70fn extract_single_text_node(children: &Element) -> Result<String, ExtractSingleTextNodeError<'_>> {
71 let vnode = match children {
72 Element::Ok(vnode) => vnode,
73 Element::Err(err) => {
74 return Err(ExtractSingleTextNodeError::RenderError(err));
75 }
76 };
77 match vnode.template {
81 Template {
83 roots: &[TemplateNode::Text { text }],
84 node_paths: &[],
85 attr_paths: &[],
86 ..
87 } => Ok(text.to_string()),
88 Template {
90 roots: &[TemplateNode::Dynamic { id }],
91 node_paths: &[&[0]],
92 attr_paths: &[],
93 ..
94 } => {
95 let node = &vnode.dynamic_nodes[id];
96 match node {
97 DynamicNode::Text(text) => Ok(text.value.clone()),
98 _ => Err(ExtractSingleTextNodeError::NonTextNode),
99 }
100 }
101 _ => Err(ExtractSingleTextNodeError::NonTemplate),
102 }
103}
104
105fn get_or_insert_root_context<T: Default + Clone + 'static>() -> T {
106 let rt = Runtime::current();
107 match rt.has_context::<T>(ScopeId::ROOT) {
108 Some(context) => context,
109 None => {
110 let context = T::default();
111 rt.provide_context(ScopeId::ROOT, context.clone());
112 context
113 }
114 }
115}
116
117#[derive(Default, Clone)]
118struct DeduplicationContext(Rc<RefCell<HashSet<String>>>);
119
120impl DeduplicationContext {
121 fn should_insert(&self, href: &str) -> bool {
122 let mut set = self.0.borrow_mut();
123 let present = set.contains(href);
124 if !present {
125 set.insert(href.to_string());
126 true
127 } else {
128 false
129 }
130 }
131}
132
133pub(crate) fn extend_attributes(
135 attributes: &mut Vec<(&'static str, String)>,
136 additional_attributes: &[Attribute],
137) {
138 for additional_attribute in additional_attributes {
139 let attribute_value_as_string = match &additional_attribute.value {
140 dioxus_core::AttributeValue::Text(v) => v.to_string(),
141 dioxus_core::AttributeValue::Float(v) => v.to_string(),
142 dioxus_core::AttributeValue::Int(v) => v.to_string(),
143 dioxus_core::AttributeValue::Bool(v) => v.to_string(),
144 dioxus_core::AttributeValue::Listener(_) | dioxus_core::AttributeValue::Any(_) => {
145 tracing::error!("document::* elements do not support event listeners or any value attributes. Expected displayable attribute, found {:?}", additional_attribute.value);
146 continue;
147 }
148 dioxus_core::AttributeValue::None => {
149 continue;
150 }
151 };
152 attributes.push((additional_attribute.name, attribute_value_as_string));
153 }
154}