Skip to main content

html2md/
codes.rs

1use super::StructuredPrinter;
2use super::TagHandler;
3use crate::markup5ever_rcdom::{Handle, NodeData};
4
5#[derive(Default)]
6pub struct CodeHandler {
7    code_type: String,
8}
9
10impl CodeHandler {
11    fn find_code_child(handle: &Handle) -> Option<Handle> {
12        for child in handle.children.borrow().iter() {
13            if let NodeData::Element { ref name, .. } = child.data
14                && name.local.as_ref() == "code" {
15                    return Some(child.clone());
16                }
17        }
18        None
19    }
20
21    /// Used in both starting and finishing handling
22    fn do_handle(&mut self, printer: &mut StructuredPrinter, start: Option<&Handle>) {
23        let immediate_parent = printer.parent_chain.last().unwrap().to_owned();
24        if self.code_type == "code" && immediate_parent == "pre" {
25            // we are already in "code" mode
26            return;
27        }
28
29        match self.code_type.as_ref() {
30            "pre" => {
31                // code block should have its own paragraph
32                if start.is_some() {
33                    printer.insert_newline();
34                }
35                printer.append_str("\n```");
36
37                if let Some(handle) = start.and_then(Self::find_code_child)
38                    && let NodeData::Element { ref attrs, .. } = handle.data {
39                        let attrs = attrs.borrow();
40                        let class = attrs
41                            .iter()
42                            .find(|attr| attr.name.local.to_string() == "class");
43                        if let Some(class) = class {
44                            let class = &*class.value;
45                            let lang = class
46                                .split(" ")
47                                .filter_map(|v| v.strip_prefix("language-"))
48                                .next();
49                            if let Some(lang) = lang {
50                                printer.append_str(lang);
51                            }
52                        }
53                    }
54
55                printer.insert_newline();
56
57                if start.is_none() {
58                    printer.insert_newline();
59                }
60            }
61            "code" | "samp" => printer.append_str("`"),
62            _ => {}
63        }
64    }
65}
66
67impl TagHandler for CodeHandler {
68    fn handle(&mut self, tag: &Handle, printer: &mut StructuredPrinter) {
69        self.code_type = match tag.data {
70            NodeData::Element { ref name, .. } => name.local.to_string(),
71            _ => String::new(),
72        };
73
74        self.do_handle(printer, Some(tag));
75    }
76    fn after_handle(&mut self, printer: &mut StructuredPrinter) {
77        self.do_handle(printer, None);
78    }
79}