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 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 return;
27 }
28
29 match self.code_type.as_ref() {
30 "pre" => {
31 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}