html2md/
anchors.rs

1use crate::common::get_tag_attr;
2use crate::dummy::IdentityHandler;
3use crate::markup5ever_rcdom;
4use percent_encoding::percent_decode_str;
5
6use super::StructuredPrinter;
7use super::TagHandler;
8
9use markup5ever_rcdom::{Handle, NodeData};
10
11#[derive(Default)]
12pub struct AnchorHandler {
13    start_pos: usize,
14    url: String,
15    emit_unchanged: bool,
16}
17
18impl TagHandler for AnchorHandler {
19    fn handle(&mut self, tag: &Handle, printer: &mut StructuredPrinter) {
20        // Check for a `name` attribute. If it exists, we can't support this
21        // in markdown, so we must emit this tag unchanged.
22        if get_tag_attr(tag, "name").is_some() {
23            let mut identity = IdentityHandler;
24            identity.handle(tag, printer);
25            self.emit_unchanged = true;
26        }
27
28        self.start_pos = printer.data.len();
29
30        // try to extract a hyperlink
31        self.url = match tag.data {
32            NodeData::Element { ref attrs, .. } => {
33                let attrs = attrs.borrow();
34                let href = attrs
35                    .iter()
36                    .find(|attr| attr.name.local.to_string() == "href");
37                match href {
38                    Some(link) => {
39                        let link = &*link.value;
40                        let link = percent_decode_str(link).decode_utf8().unwrap_or_default();
41
42                        if link.contains(|c: char| c.is_ascii_whitespace()) {
43                            format!("<{}>", link)
44                        } else {
45                            link.to_string()
46                        }
47                    }
48                    None => String::new(),
49                }
50            }
51            _ => String::new(),
52        };
53    }
54
55    fn after_handle(&mut self, printer: &mut StructuredPrinter) {
56        if !self.emit_unchanged {
57            // add braces around already present text, put an url afterwards
58            printer.insert_str(self.start_pos, "[");
59            printer.append_str(&format!("]({})", self.url))
60        }
61    }
62}