1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::browser::util;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
pub fn current() -> Url {
let current_url = util::window().location().href().expect("get `href`");
web_sys::Url::new(¤t_url)
.expect("create `web_sys::Url` from the current URL")
.into()
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Url {
pub path: Vec<String>,
pub search: Option<String>,
pub hash: Option<String>,
pub title: Option<String>,
}
impl Url {
pub fn new<T: ToString>(path: Vec<T>) -> Self {
Self {
path: path.into_iter().map(|p| p.to_string()).collect(),
hash: None,
search: None,
title: None,
}
}
pub fn hash(mut self, hash: &str) -> Self {
self.hash = Some(hash.into());
self
}
pub fn search(mut self, search: &str) -> Self {
self.search = Some(search.into());
self
}
pub fn title(mut self, title: &str) -> Self {
self.title = Some(title.into());
self
}
}
impl From<web_sys::Url> for Url {
fn from(url: web_sys::Url) -> Self {
let path = {
let mut path = url.pathname();
path.remove(0);
path.split('/').map(ToOwned::to_owned).collect::<Vec<_>>()
};
let hash = {
let mut hash = url.hash();
if hash.is_empty() {
None
} else {
hash.remove(0);
Some(hash)
}
};
let search = {
let mut search = url.search();
if search.is_empty() {
None
} else {
search.remove(0);
Some(search)
}
};
Self {
path,
hash,
search,
title: None,
}
}
}
impl TryFrom<String> for Url {
type Error = String;
fn try_from(relative_url: String) -> Result<Self, Self::Error> {
let dummy_base_url = "http://example.com";
web_sys::Url::new_with_base(&relative_url, dummy_base_url)
.map(Url::from)
.map_err(|_| format!("`{}` is invalid relative URL", relative_url))
}
}
impl From<Vec<String>> for Url {
fn from(path: Vec<String>) -> Self {
Url::new(path)
}
}
impl From<Vec<&str>> for Url {
fn from(path: Vec<&str>) -> Self {
Url::new(path)
}
}