lithe/
document_type.rs

1use crate::dtd::DTD;
2
3// https://developer.mozilla.org/en-US/docs/Web/API/DocumentType
4#[derive(Clone, Debug, Eq, PartialEq)]
5pub struct DocumentType<'a> {
6    dtd: DTD<'a>,
7    pub name: &'a str,
8    pub public_id: &'static str,
9    pub system_id: &'static str,
10}
11
12impl<'a> DocumentType<'a> {
13    pub fn new(r#type: &'static str, name: &'a str) -> Self {
14        let dtd = DTD::new(r#type, name);
15        let public_id = dtd.public_id();
16        let system_id = dtd.system_id();
17
18        Self {
19            dtd,
20            name,
21            public_id,
22            system_id,
23        }
24    }
25
26    pub fn as_tag(&self) -> String {
27        let mut out = "<!DOCTYPE".to_string();
28        let dec = match self.dtd.spec {
29            "html" => match self.dtd.name {
30                "5" | "html" => " HTML>".to_string(),
31                _ => format!(
32                    " HTML PUBLIC \"{}\" \"{}\">",
33                    self.public_id, self.system_id
34                ),
35            },
36            "xhtml" => format!(
37                " html PUBLIC \"{}\" \"{}\">",
38                self.public_id, self.system_id
39            ),
40            _ => "".to_string(),
41        };
42        out.push_str(&dec);
43        out
44    }
45}
46
47#[cfg(test)]
48mod test {
49    use super::*;
50
51    #[test]
52    fn test_document_type_new() {
53        let doctype = DocumentType::new("unknown", "invalid");
54        assert_eq!(doctype.name, "invalid");
55        assert_eq!(doctype.public_id, "");
56        assert_eq!(doctype.system_id, "");
57
58        let doctype = DocumentType::new("unknown", "strict");
59        assert_eq!(doctype.name, "strict");
60        assert_eq!(doctype.public_id, "");
61        assert_eq!(doctype.system_id, "");
62
63        let doctype = DocumentType::new("xhtml", "invalid");
64        assert_eq!(doctype.name, "invalid");
65        assert_eq!(doctype.public_id, "");
66        assert_eq!(doctype.system_id, "");
67
68        let doctype = DocumentType::new("xhtml", "frameset");
69        assert_eq!(doctype.name, "frameset");
70        assert_eq!(doctype.public_id, "-//W3C//DTD XHTML 1.0 Frameset//EN");
71        assert_eq!(
72            doctype.system_id,
73            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
74        );
75
76        let doctype = DocumentType::new("html", "invalid");
77        assert_eq!(doctype.name, "invalid");
78        assert_eq!(doctype.public_id, "");
79        assert_eq!(doctype.system_id, "");
80
81        let doctype = DocumentType::new("html", "transitional");
82        assert_eq!(doctype.name, "transitional");
83        assert_eq!(doctype.public_id, "-//W3C//DTD HTML 4.01 Transitional//EN");
84        assert_eq!(doctype.system_id, "http://www.w3.org/TR/html4/loose.dtd");
85    }
86
87    #[test]
88    fn test_as_tag() {
89        let doctype = DocumentType::new("html", "5");
90        assert_eq!(doctype.as_tag(), "<!DOCTYPE HTML>");
91
92        let doctype = DocumentType::new("html", "strict");
93        assert_eq!(
94            doctype.as_tag(),
95            inline!(
96                r#"<!DOCTYPE
97 HTML
98 PUBLIC
99 "-//W3C//DTD HTML 4.01//EN"
100 "http://www.w3.org/TR/html4/strict.dtd"
101>"#
102            )
103        );
104
105        let doctype = DocumentType::new("html", "frameset");
106        assert_eq!(
107            doctype.as_tag(),
108            inline!(
109                r#"<!DOCTYPE
110 HTML
111 PUBLIC
112 "-//W3C//DTD HTML 4.01 Frameset//EN"
113 "http://www.w3.org/TR/html4/frameset.dtd"
114>"#
115            )
116        );
117
118        let doctype = DocumentType::new("html", "transitional");
119        assert_eq!(
120            doctype.as_tag(),
121            inline!(
122                r#"<!DOCTYPE
123 HTML
124 PUBLIC
125 "-//W3C//DTD HTML 4.01 Transitional//EN"
126 "http://www.w3.org/TR/html4/loose.dtd"
127>"#
128            )
129        );
130    }
131}