html2md/
anchors.rs

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