dioxus_document/elements/
link.rs

1use super::*;
2use crate::document;
3use dioxus_html as dioxus_elements;
4
5#[non_exhaustive]
6#[derive(Clone, Props, PartialEq)]
7pub struct LinkProps {
8    pub rel: Option<String>,
9    pub media: Option<String>,
10    pub title: Option<String>,
11    pub disabled: Option<bool>,
12    pub r#as: Option<String>,
13    pub sizes: Option<String>,
14    /// Links are deduplicated by their href attribute
15    pub href: Option<String>,
16    pub crossorigin: Option<String>,
17    pub referrerpolicy: Option<String>,
18    pub fetchpriority: Option<String>,
19    pub hreflang: Option<String>,
20    pub integrity: Option<String>,
21    pub r#type: Option<String>,
22    pub blocking: Option<String>,
23    #[props(extends = link, extends = GlobalAttributes)]
24    pub additional_attributes: Vec<Attribute>,
25}
26
27impl LinkProps {
28    /// Get all the attributes for the link tag
29    pub fn attributes(&self) -> Vec<(&'static str, String)> {
30        let mut attributes = Vec::new();
31        extend_attributes(&mut attributes, &self.additional_attributes);
32        if let Some(rel) = &self.rel {
33            attributes.push(("rel", rel.clone()));
34        }
35        if let Some(media) = &self.media {
36            attributes.push(("media", media.clone()));
37        }
38        if let Some(title) = &self.title {
39            attributes.push(("title", title.clone()));
40        }
41        if let Some(disabled) = &self.disabled {
42            attributes.push(("disabled", disabled.to_string()));
43        }
44        if let Some(r#as) = &self.r#as {
45            attributes.push(("as", r#as.clone()));
46        }
47        if let Some(sizes) = &self.sizes {
48            attributes.push(("sizes", sizes.clone()));
49        }
50        if let Some(href) = &self.href {
51            attributes.push(("href", href.clone()));
52        }
53        if let Some(crossorigin) = &self.crossorigin {
54            attributes.push(("crossOrigin", crossorigin.clone()));
55        }
56        if let Some(referrerpolicy) = &self.referrerpolicy {
57            attributes.push(("referrerPolicy", referrerpolicy.clone()));
58        }
59        if let Some(fetchpriority) = &self.fetchpriority {
60            attributes.push(("fetchPriority", fetchpriority.clone()));
61        }
62        if let Some(hreflang) = &self.hreflang {
63            attributes.push(("hrefLang", hreflang.clone()));
64        }
65        if let Some(integrity) = &self.integrity {
66            attributes.push(("integrity", integrity.clone()));
67        }
68        if let Some(r#type) = &self.r#type {
69            attributes.push(("type", r#type.clone()));
70        }
71        if let Some(blocking) = &self.blocking {
72            attributes.push(("blocking", blocking.clone()));
73        }
74        attributes
75    }
76}
77
78/// Render a [`link`](crate::elements::link) tag into the head of the page.
79///
80/// > The [Link](https://docs.rs/dioxus-router/latest/dioxus_router/components/fn.Link.html) component in dioxus router and this component are completely different.
81/// > This component links resources in the head of the page, while the router component creates clickable links in the body of the page.
82///
83/// # Example
84/// ```rust, no_run
85/// # use dioxus::prelude::*;
86/// fn RedBackground() -> Element {
87///     rsx! {
88///         // You can use the meta component to render a meta tag into the head of the page
89///         // This meta tag will redirect the user to the dioxuslabs homepage in 10 seconds
90///         document::Link {
91///             href: asset!("/assets/style.css"),
92///             rel: "stylesheet",
93///         }
94///     }
95/// }
96/// ```
97///
98/// <div class="warning">
99///
100/// Any updates to the props after the first render will not be reflected in the head.
101///
102/// </div>
103#[doc(alias = "<link>")]
104#[component]
105pub fn Link(props: LinkProps) -> Element {
106    use_update_warning(&props, "Link {}");
107
108    use_hook(|| {
109        let document = document();
110        let mut insert_link = document.create_head_component();
111        if let Some(href) = &props.href {
112            if !should_insert_link(href) {
113                insert_link = false;
114            }
115        }
116
117        if !insert_link {
118            return;
119        }
120
121        document.create_link(props);
122    });
123
124    VNode::empty()
125}
126
127#[derive(Default, Clone)]
128struct LinkContext(DeduplicationContext);
129
130fn should_insert_link(href: &str) -> bool {
131    get_or_insert_root_context::<LinkContext>()
132        .0
133        .should_insert(href)
134}