1use linkify::{LinkFinder, LinkKind};
2use yew::prelude::*;
3
4#[derive(Properties, PartialEq)]
5pub struct Props {
6 pub text: String,
7}
8
9#[function_component]
10pub fn Linkify(props: &Props) -> Html {
11 let finder = LinkFinder::new();
12 let text = props.text.as_str();
13 let spans = finder.spans(text);
14
15 html! {
16 <p>
17 {
18 for spans.into_iter().map(move |current| {
19
20 match current.kind() {
21
22 Some(LinkKind::Email) => {
23 let mut mail_to_link: String = "mailto:".to_owned();
24 let current_string: &str = current.as_str();
25
26 mail_to_link.push_str(current_string);
27 return html!{<a href={mail_to_link}>{current.as_str()}</a>}
28 }
29
30 Some(LinkKind::Url) => {
31 let mut plain_link: String = "".to_owned();
33 let current_string: &str = current.as_str();
34 plain_link.push_str(current_string);
35
36 return html!{<a href={plain_link}>{current.as_str()}</a>}
37 }
38 _ => {
39 return html!{
40 <span>{current.as_str()}</span>
41 }
42 }
43 }
44
45 })
46 }
47 </p>
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use linkify::{LinkFinder, LinkKind};
54
55 #[test]
56 fn test_linkify_email() {
57 let finder = LinkFinder::new();
58 let text = "Contact: test@example.com";
59 let spans: Vec<_> = finder.spans(text).collect();
60 assert!(spans.iter().any(|s| s.kind() == Some(&LinkKind::Email)));
61 }
62
63 #[test]
64 fn test_linkify_url() {
65 let finder = LinkFinder::new();
66 let text = "Visit https://example.com!";
67 let spans: Vec<_> = finder.spans(text).collect();
68 assert!(spans.iter().any(|s| s.kind() == Some(&LinkKind::Url)));
69 }
70}