1use super::{html, markdown_v2, Formattable, Nesting};
2use crate::types::user;
3use std::{
4 fmt::{self, Formatter, Write},
5 ops::Deref,
6};
7
8#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
9enum Kind<T> {
10 Link(T),
11 Mention(user::Id),
12}
13
14#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
19#[must_use = "formatters need to be formatted with `markdown_v2` or `html`"]
20pub struct Link<T, L = &'static str> {
21 text: T,
22 link: Kind<L>,
23}
24
25pub fn link<T, L>(text: T, link: L) -> Link<T, L>
27where
28 T: Formattable,
29 L: Deref<Target = str>,
30{
31 Link {
32 text,
33 link: Kind::Link(link),
34 }
35}
36
37pub fn mention<T: Formattable>(text: T, user: user::Id) -> Link<T> {
39 Link {
40 text,
41 link: Kind::Mention(user),
42 }
43}
44
45impl<T, L> markdown_v2::Formattable for Link<T, L>
46where
47 T: Formattable,
48 L: Deref<Target = str>,
49{
50 fn format(
51 &self,
52 formatter: &mut Formatter,
53 nesting: Nesting,
54 ) -> fmt::Result {
55 formatter.write_char('[')?;
56 markdown_v2::Formattable::format(&self.text, formatter, nesting)?;
57 formatter.write_str("](")?;
58
59 match &self.link {
60 Kind::Link(link) => link
61 .deref()
62 .chars()
63 .map(|x| {
64 if markdown_v2::ESCAPED_LINK_CHARACTERS.contains(&x) {
65 formatter.write_char('\\')?;
66 }
67 formatter.write_char(x)
68 })
69 .collect::<Result<(), _>>()?,
70 Kind::Mention(user::Id(id)) => {
71 write!(formatter, "tg://user?id={}", id)?
72 }
73 }
74 formatter.write_char(')')
75 }
76}
77
78impl<T, L> html::Formattable for Link<T, L>
79where
80 T: Formattable,
81 L: Deref<Target = str>,
82{
83 fn format(
84 &self,
85 formatter: &mut Formatter,
86 nesting: Nesting,
87 ) -> fmt::Result {
88 formatter.write_str("<a href=\"")?;
89
90 match &self.link {
91 Kind::Link(link) => link
92 .deref()
93 .chars()
94 .map(|x| {
95 if x == '"' {
96 formatter.write_char('\\')?;
97 }
98 formatter.write_char(x)
99 })
100 .collect::<Result<(), _>>()?,
101 Kind::Mention(user::Id(id)) => {
102 write!(formatter, "tg://user?id={}", id)?
103 }
104 }
105
106 formatter.write_str("\">")?;
107 html::Formattable::format(&self.text, formatter, nesting)?;
108 formatter.write_str("</a>")
109 }
110}