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