yew_stdweb/
utils.rs

1//! This module contains useful utilities to get information about the current document.
2
3use anyhow::{anyhow, Error};
4use cfg_if::cfg_if;
5use cfg_match::cfg_match;
6use std::marker::PhantomData;
7use yew::html::ChildrenRenderer;
8cfg_if! {
9    if #[cfg(feature = "std_web")] {
10        use stdweb::web::{Document, Window};
11    } else if #[cfg(feature = "web_sys")] {
12        use web_sys::{Document, Window};
13    }
14}
15
16/// Returns the current window. This function will panic if there is no available window.
17pub fn window() -> Window {
18    cfg_match! {
19        feature = "std_web" => stdweb::web::window(),
20        feature = "web_sys" => web_sys::window().expect("no window available"),
21    }
22}
23
24/// Returns the current document.
25pub fn document() -> Document {
26    cfg_match! {
27        feature = "std_web" => stdweb::web::document(),
28        feature = "web_sys" => window().document().unwrap(),
29    }
30}
31
32/// Returns the `host` for the current document. Useful for connecting to the server which serves
33/// the app.
34pub fn host() -> Result<String, Error> {
35    let location = document()
36        .location()
37        .ok_or_else(|| anyhow!("can't get location"))?;
38
39    #[cfg(feature = "std_web")]
40    let host = location.host().map_err(Error::from)?;
41
42    #[cfg(feature = "web_sys")]
43    let host = location.host().map_err(|e| {
44        anyhow!(e
45            .as_string()
46            .unwrap_or_else(|| String::from("error not recoverable")),)
47    })?;
48
49    Ok(host)
50}
51
52/// Returns the `origin` of the current window.
53pub fn origin() -> Result<String, Error> {
54    let location = window().location();
55
56    #[cfg(feature = "std_web")]
57    let location = location.ok_or_else(|| anyhow!("can't get location"))?;
58
59    #[cfg(feature = "std_web")]
60    let origin = location.origin().map_err(Error::from)?;
61
62    #[cfg(feature = "web_sys")]
63    let origin = location.origin().map_err(|e| {
64        anyhow!(e
65            .as_string()
66            .unwrap_or_else(|| String::from("error not recoverable")),)
67    })?;
68
69    Ok(origin)
70}
71
72/// Map IntoIterator<Item=Into<T>> to Iterator<Item=T>
73pub fn into_node_iter<IT, T, R>(it: IT) -> impl Iterator<Item = R>
74where
75    IT: IntoIterator<Item = T>,
76    T: Into<R>,
77{
78    it.into_iter().map(|n| n.into())
79}
80
81/// A special type necessary for flattening components returned from nested html macros.
82#[derive(Debug)]
83pub struct NodeSeq<IN, OUT>(Vec<OUT>, PhantomData<IN>);
84
85impl<IN: Into<OUT>, OUT> From<IN> for NodeSeq<IN, OUT> {
86    fn from(val: IN) -> Self {
87        Self(vec![val.into()], PhantomData::default())
88    }
89}
90
91impl<IN: Into<OUT>, OUT> From<Vec<IN>> for NodeSeq<IN, OUT> {
92    fn from(val: Vec<IN>) -> Self {
93        Self(
94            val.into_iter().map(|x| x.into()).collect(),
95            PhantomData::default(),
96        )
97    }
98}
99
100impl<IN: Into<OUT>, OUT> From<ChildrenRenderer<IN>> for NodeSeq<IN, OUT> {
101    fn from(val: ChildrenRenderer<IN>) -> Self {
102        Self(
103            val.into_iter().map(|x| x.into()).collect(),
104            PhantomData::default(),
105        )
106    }
107}
108
109impl<IN, OUT> IntoIterator for NodeSeq<IN, OUT> {
110    type Item = OUT;
111    type IntoIter = std::vec::IntoIter<Self::Item>;
112
113    fn into_iter(self) -> Self::IntoIter {
114        self.0.into_iter()
115    }
116}