1use is_macro::Is;
2use string_enum::StringEnum;
3use swc_atoms::Atom;
4use swc_common::{ast_node, EqIgnoreSpan, Span};
5
6#[ast_node("Document")]
7#[derive(Eq, Hash, EqIgnoreSpan)]
8pub struct Document {
9 pub span: Span,
10 pub mode: DocumentMode,
11 pub children: Vec<Child>,
12}
13
14#[ast_node("DocumentFragment")]
15#[derive(Eq, Hash, EqIgnoreSpan)]
16pub struct DocumentFragment {
17 pub span: Span,
18 pub children: Vec<Child>,
19}
20
21#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
22#[cfg_attr(
23 feature = "rkyv",
24 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
25)]
26#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
27#[cfg_attr(feature = "rkyv", repr(u32))]
33pub enum DocumentMode {
34 NoQuirks,
36 LimitedQuirks,
38 Quirks,
40}
41
42#[ast_node]
43#[derive(Eq, Hash, Is, EqIgnoreSpan)]
44pub enum Child {
45 #[tag("DocumentType")]
46 DocumentType(DocumentType),
47 #[tag("Element")]
48 Element(Element),
49 #[tag("Text")]
50 Text(Text),
51 #[tag("Comment")]
52 Comment(Comment),
53}
54
55#[ast_node("DocumentType")]
56#[derive(Eq, Hash)]
57pub struct DocumentType {
58 pub span: Span,
59
60 pub name: Option<Atom>,
61
62 pub public_id: Option<Atom>,
63
64 pub system_id: Option<Atom>,
65 pub raw: Option<Atom>,
66}
67
68impl EqIgnoreSpan for DocumentType {
69 fn eq_ignore_span(&self, other: &Self) -> bool {
70 self.name == other.name
71 && self.public_id == other.public_id
72 && self.system_id == other.system_id
73 }
74}
75
76#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
77#[cfg_attr(
78 feature = "rkyv",
79 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
80)]
81#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
82#[cfg_attr(feature = "rkyv", repr(u32))]
88pub enum Namespace {
89 HTML,
91 MATHML,
93 SVG,
95 XLINK,
97 XML,
99 XMLNS,
101}
102
103#[ast_node("Element")]
104#[derive(Eq, Hash, EqIgnoreSpan)]
105pub struct Element {
106 pub span: Span,
107
108 pub tag_name: Atom,
109 pub namespace: Namespace,
110 pub attributes: Vec<Attribute>,
111 pub children: Vec<Child>,
112 pub content: Option<DocumentFragment>,
114 pub is_self_closing: bool,
115}
116
117#[ast_node("Attribute")]
118#[derive(Eq, Hash)]
119pub struct Attribute {
120 pub span: Span,
121 pub namespace: Option<Namespace>,
122
123 pub prefix: Option<Atom>,
124
125 pub name: Atom,
126 pub raw_name: Option<Atom>,
127
128 pub value: Option<Atom>,
129 pub raw_value: Option<Atom>,
130}
131
132impl EqIgnoreSpan for Attribute {
133 fn eq_ignore_span(&self, other: &Self) -> bool {
134 self.namespace == other.namespace
135 && self.prefix == other.prefix
136 && self.name == other.name
137 && self.value == other.value
138 }
139}
140
141#[ast_node("Text")]
142#[derive(Eq, Hash)]
143pub struct Text {
144 pub span: Span,
145
146 pub data: Atom,
147 pub raw: Option<Atom>,
148}
149
150impl EqIgnoreSpan for Text {
151 fn eq_ignore_span(&self, other: &Self) -> bool {
152 self.data == other.data
153 }
154}
155
156#[ast_node("Comment")]
157#[derive(Eq, Hash)]
158pub struct Comment {
159 pub span: Span,
160
161 pub data: Atom,
162 pub raw: Option<Atom>,
163}
164
165impl EqIgnoreSpan for Comment {
166 fn eq_ignore_span(&self, other: &Self) -> bool {
167 self.data == other.data
168 }
169}