Skip to main content

swc_ecma_codegen/
jsx.rs

1use swc_common::{BytePos, SourceMapper, Spanned};
2use swc_ecma_ast::*;
3use swc_ecma_codegen_macros::node_impl;
4
5use super::Emitter;
6use crate::text_writer::WriteJs;
7#[cfg(swc_ast_unknown)]
8use crate::unknown_error;
9
10impl<W, S: SourceMapper> Emitter<'_, W, S>
11where
12    W: WriteJs,
13    S: SourceMapperExt,
14{
15}
16
17#[node_impl]
18impl MacroNode for JSXElement {
19    fn emit(&mut self, emitter: &mut Macro) -> Result {
20        emitter.emit_leading_comments_of_span(self.span(), false)?;
21        emit!(self.opening);
22        emitter.emit_list(
23            self.span(),
24            Some(&self.children),
25            ListFormat::JsxElementOrFragmentChildren,
26        )?;
27        if let Some(ref closing) = self.closing {
28            emit!(closing)
29        }
30        Ok(())
31    }
32}
33
34#[node_impl]
35impl MacroNode for JSXOpeningElement {
36    fn emit(&mut self, emitter: &mut Macro) -> Result {
37        punct!(emitter, "<");
38        emit!(self.name);
39
40        if let Some(type_args) = &self.type_args {
41            emit!(type_args);
42        }
43
44        if !self.attrs.is_empty() {
45            space!(emitter);
46
47            emitter.emit_list(
48                self.span(),
49                Some(&self.attrs),
50                ListFormat::JsxElementAttributes,
51            )?;
52        }
53
54        if self.self_closing {
55            punct!(emitter, "/");
56        }
57        punct!(emitter, ">");
58        Ok(())
59    }
60}
61
62#[node_impl]
63impl MacroNode for JSXElementName {
64    fn emit(&mut self, emitter: &mut Macro) -> Result {
65        match *self {
66            JSXElementName::Ident(ref n) => emit!(n),
67            JSXElementName::JSXMemberExpr(ref n) => emit!(n),
68            JSXElementName::JSXNamespacedName(ref n) => emit!(n),
69            #[cfg(swc_ast_unknown)]
70            _ => return Err(unknown_error()),
71        }
72        Ok(())
73    }
74}
75
76#[node_impl]
77impl MacroNode for JSXAttr {
78    fn emit(&mut self, emitter: &mut Macro) -> Result {
79        emit!(self.name);
80
81        if let Some(ref value) = self.value {
82            punct!(emitter, "=");
83            emit!(value);
84        }
85        Ok(())
86    }
87}
88
89#[node_impl]
90impl MacroNode for JSXAttrValue {
91    fn emit(&mut self, emitter: &mut Macro) -> Result {
92        match *self {
93            JSXAttrValue::Str(ref n) => emit!(n),
94            JSXAttrValue::JSXExprContainer(ref n) => emit!(n),
95            JSXAttrValue::JSXElement(ref n) => emit!(n),
96            JSXAttrValue::JSXFragment(ref n) => emit!(n),
97            #[cfg(swc_ast_unknown)]
98            _ => return Err(unknown_error()),
99        }
100        Ok(())
101    }
102}
103
104#[node_impl]
105impl MacroNode for JSXAttrName {
106    fn emit(&mut self, emitter: &mut Macro) -> Result {
107        match *self {
108            JSXAttrName::Ident(ref n) => emit!(n),
109            JSXAttrName::JSXNamespacedName(ref n) => emit!(n),
110            #[cfg(swc_ast_unknown)]
111            _ => return Err(unknown_error()),
112        }
113        Ok(())
114    }
115}
116
117#[node_impl]
118impl MacroNode for JSXAttrOrSpread {
119    fn emit(&mut self, emitter: &mut Macro) -> Result {
120        match *self {
121            JSXAttrOrSpread::JSXAttr(ref n) => emit!(n),
122            JSXAttrOrSpread::SpreadElement(ref n) => {
123                punct!(emitter, "{");
124                emit!(n);
125                punct!(emitter, "}");
126            }
127            #[cfg(swc_ast_unknown)]
128            _ => return Err(unknown_error()),
129        }
130        Ok(())
131    }
132}
133
134#[node_impl]
135impl MacroNode for JSXElementChild {
136    fn emit(&mut self, emitter: &mut Macro) -> Result {
137        match *self {
138            JSXElementChild::JSXElement(ref n) => emit!(n),
139            JSXElementChild::JSXExprContainer(ref n) => emit!(n),
140            JSXElementChild::JSXFragment(ref n) => emit!(n),
141            JSXElementChild::JSXSpreadChild(ref n) => emit!(n),
142            JSXElementChild::JSXText(ref n) => emit!(n),
143            #[cfg(swc_ast_unknown)]
144            _ => return Err(unknown_error()),
145        }
146        Ok(())
147    }
148}
149
150#[node_impl]
151impl MacroNode for JSXSpreadChild {
152    fn emit(&mut self, emitter: &mut Macro) -> Result {
153        punct!(emitter, "{");
154        punct!(emitter, "...");
155        emit!(self.expr);
156        punct!(emitter, "}");
157        Ok(())
158    }
159}
160
161#[node_impl]
162impl MacroNode for JSXExprContainer {
163    fn emit(&mut self, emitter: &mut Macro) -> Result {
164        punct!(emitter, "{");
165        emitter.emit_trailing_comments_of_pos(self.span.lo + BytePos(1), true, false)?;
166        emit!(self.expr);
167        punct!(emitter, "}");
168        Ok(())
169    }
170}
171
172#[node_impl]
173impl MacroNode for JSXExpr {
174    fn emit(&mut self, emitter: &mut Macro) -> Result {
175        match *self {
176            JSXExpr::Expr(ref n) => emit!(n),
177            JSXExpr::JSXEmptyExpr(ref n) => emit!(n),
178            #[cfg(swc_ast_unknown)]
179            _ => return Err(unknown_error()),
180        }
181        Ok(())
182    }
183}
184
185#[node_impl]
186impl MacroNode for JSXClosingElement {
187    fn emit(&mut self, emitter: &mut Macro) -> Result {
188        punct!(emitter, "</");
189        emit!(self.name);
190        punct!(emitter, ">");
191        Ok(())
192    }
193}
194
195#[node_impl]
196impl MacroNode for JSXFragment {
197    fn emit(&mut self, emitter: &mut Macro) -> Result {
198        emitter.emit_leading_comments_of_span(self.span(), false)?;
199        emit!(self.opening);
200
201        emitter.emit_list(
202            self.span(),
203            Some(&self.children),
204            ListFormat::JsxElementOrFragmentChildren,
205        )?;
206
207        emit!(self.closing);
208        Ok(())
209    }
210}
211
212#[node_impl]
213impl MacroNode for JSXOpeningFragment {
214    fn emit(&mut self, emitter: &mut Macro) -> Result {
215        punct!(emitter, "<>");
216        Ok(())
217    }
218}
219
220#[node_impl]
221impl MacroNode for JSXClosingFragment {
222    fn emit(&mut self, emitter: &mut Macro) -> Result {
223        punct!(emitter, "</>");
224        Ok(())
225    }
226}
227
228#[node_impl]
229impl MacroNode for JSXNamespacedName {
230    fn emit(&mut self, emitter: &mut Macro) -> Result {
231        emit!(self.ns);
232        punct!(emitter, ":");
233        emit!(self.name);
234        Ok(())
235    }
236}
237
238#[node_impl]
239impl MacroNode for JSXEmptyExpr {
240    fn emit(&mut self, emitter: &mut Macro) -> Result {
241        emitter.emit_leading_comments_of_span(self.span, false)?;
242        Ok(())
243    }
244}
245
246#[node_impl]
247impl MacroNode for JSXText {
248    fn emit(&mut self, emitter: &mut Macro) -> Result {
249        emitter.emit_atom(self.span(), &self.raw)?;
250        Ok(())
251    }
252}
253
254#[node_impl]
255impl MacroNode for JSXMemberExpr {
256    fn emit(&mut self, emitter: &mut Macro) -> Result {
257        emit!(self.obj);
258        punct!(emitter, ".");
259        emit!(self.prop);
260        Ok(())
261    }
262}
263
264#[node_impl]
265impl MacroNode for JSXObject {
266    fn emit(&mut self, emitter: &mut Macro) -> Result {
267        match *self {
268            JSXObject::Ident(ref n) => emit!(n),
269            JSXObject::JSXMemberExpr(ref n) => emit!(n),
270            #[cfg(swc_ast_unknown)]
271            _ => return Err(unknown_error()),
272        }
273        Ok(())
274    }
275}