1use crate::dtd::DTD;
2
3#[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}