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
use {
crate::*,
indexmap::IndexMap,
termimad::crossterm::style::Stylize,
};
/// A single link in the navigation bar
#[derive(Debug, Clone, PartialEq)]
pub struct NavLink {
pub href: Option<String>,
pub target: Option<String>,
pub content: Vec<NavLinkPart>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum NavLinkPart {
Label(Text),
Img { src: String, alt: Option<String> },
InlineImg { src: String },
}
impl From<Attributes> for NavLink {
fn from(map: IndexMap<AttributeKey, AttributeValue>) -> Self {
let mut alt = None;
let mut content = Vec::new();
let mut href = None;
let mut target = None;
for (key, value) in &map {
match key.as_str() {
"alt" => {
let mut added = false;
for part in &mut content {
if let NavLinkPart::Img { alt, .. } = part {
*alt = Some(value.to_string());
added = true;
break;
}
}
if !added {
alt = Some(value.to_string());
}
}
"img" => {
if let Some(src) = value.as_str() {
let img_part = NavLinkPart::Img {
src: src.to_string(),
alt: alt.take(),
};
content.push(img_part);
}
}
"inline" => {
if let Some(src) = value.as_str() {
let inline_part = NavLinkPart::InlineImg {
src: src.to_string(),
};
content.push(inline_part);
}
}
"label" => {
let label_part = NavLinkPart::Label(value.into());
content.push(label_part);
}
"href" | "url" => {
// note: "url" is deprecated and not documented
href = Some(value.to_string());
}
"target" | "link_target" => {
target = Some(value.to_string());
}
key => {
eprintln!(
"{}: unknown attribute in nav-link: {}",
"warning".yellow().bold(),
key.red(),
);
}
}
}
Self {
href,
target,
content,
}
}
}