Skip to content

Commit 694e1ef

Browse files
committed
Error on styled syntax
1 parent 7003278 commit 694e1ef

3 files changed

Lines changed: 49 additions & 41 deletions

File tree

packages/swc-plugin/src/lib.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ impl CompiledTransform {
172172
}
173173
imports.css_map.as_mut().unwrap().push(local_name);
174174
}
175+
"styled" => {
176+
if imports.styled.is_none() {
177+
imports.styled = Some(Vec::new());
178+
}
179+
imports.styled.as_mut().unwrap().push(local_name);
180+
}
175181
_ => {
176182
should_remove_import = false;
177183
}
@@ -312,6 +318,27 @@ impl VisitMut for CompiledTransform {
312318
}
313319

314320
fn visit_mut_call_expr(&mut self, n: &mut CallExpr) {
321+
// Error on any styled usage (styled.tag`...` or styled(tag)(...))
322+
if let Some(ref imports) = self.state.compiled_imports {
323+
if let Some(ref styled_locals) = imports.styled {
324+
// Check for styled("div")(...) pattern or styled.tag(...) pattern
325+
let is_styled_call = match &n.callee {
326+
Callee::Expr(expr) => match expr.as_ref() {
327+
Expr::Ident(ident) => styled_locals.contains(&ident.sym.to_string()),
328+
Expr::Member(MemberExpr { obj, .. }) => match obj.as_ref() {
329+
Expr::Ident(ident) => styled_locals.contains(&ident.sym.to_string()),
330+
_ => false,
331+
},
332+
_ => false,
333+
},
334+
_ => false,
335+
};
336+
if is_styled_call {
337+
panic!("styled API is not supported by the SWC plugin. Please use css/cssMap or the Babel plugin.");
338+
}
339+
}
340+
}
341+
315342
let mut handled_css_prop = false;
316343
let is_react_jsx_like = match &n.callee {
317344
Callee::Expr(callee_expr) => match callee_expr.as_ref() {
@@ -398,6 +425,20 @@ impl VisitMut for CompiledTransform {
398425
}
399426

400427
fn visit_mut_expr(&mut self, n: &mut Expr) {
428+
// Error on any styled tagged template usage like styled.div`...`
429+
if let Expr::TaggedTpl(tagged) = n {
430+
if let Expr::Member(MemberExpr { obj, .. }) = tagged.tag.as_ref() {
431+
if let Expr::Ident(ident) = obj.as_ref() {
432+
if let Some(ref imports) = self.state.compiled_imports {
433+
if let Some(ref styled_locals) = imports.styled {
434+
if styled_locals.contains(&ident.sym.to_string()) {
435+
panic!("styled API is not supported by the SWC plugin. Please use css/cssMap or the Babel plugin.");
436+
}
437+
}
438+
}
439+
}
440+
}
441+
}
401442
if let Expr::Call(call) = n {
402443
if visitors::css::is_css_call(call, &self.state) {
403444
if self.options.strict_mode {

packages/swc-plugin/src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ pub struct TransformState {
1717
pub struct CompiledImports {
1818
pub css: Option<Vec<String>>,
1919
pub css_map: Option<Vec<String>>,
20+
pub styled: Option<Vec<String>>,
2021
}
2122

2223
impl CompiledImports {
2324
pub fn new() -> Self {
2425
Self {
2526
css: None,
2627
css_map: None,
28+
styled: None,
2729
}
2830
}
2931
}

packages/swc-plugin/tests/strict-mode.test.js

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -494,63 +494,28 @@ describe('Strict Mode - SWC Plugin', () => {
494494
`);
495495
});
496496

497-
it('should not transform styled components', async () => {
497+
it('should error on styled tagged template usage', async () => {
498498
const code = `
499499
import { styled } from '@compiled/react';
500500
501501
const Button = styled.div\`
502502
color: red;
503503
\`;
504504
`;
505-
506-
const out = await transformResultString(code);
507-
expect(out).toMatchInlineSnapshot(`
508-
"function _tagged_template_literal(strings, raw) {
509-
if (!raw) {
510-
raw = strings.slice(0);
511-
}
512-
return Object.freeze(Object.defineProperties(strings, {
513-
raw: {
514-
value: Object.freeze(raw)
515-
}
516-
}));
517-
}
518-
function _templateObject() {
519-
var data = _tagged_template_literal([
520-
"\\n color: red;\\n "
521-
]);
522-
_templateObject = function _templateObject() {
523-
return data;
524-
};
525-
return data;
526-
}
527-
import * as React from "react";
528-
import { ax, ix, CC, CS } from "@compiled/react/runtime";
529-
import { styled } from "@compiled/react";
530-
var Button = styled.div(_templateObject());
531-
"
532-
`);
505+
const error = await expectToThrow(code);
506+
expectToContain(String(error), 'RuntimeError: unreachable');
533507
});
534508

535-
it('should not transform styled component calls', async () => {
509+
it('should error on styled component factory calls', async () => {
536510
const code = `
537511
import { styled } from '@compiled/react';
538512
539513
const Button = styled('div')({
540514
color: 'red'
541515
});
542516
`;
543-
544-
const out = await transformResultString(code);
545-
expect(out).toMatchInlineSnapshot(`
546-
"import * as React from "react";
547-
import { ax, ix, CC, CS } from "@compiled/react/runtime";
548-
import { styled } from "@compiled/react";
549-
var Button = styled("div")({
550-
color: "red"
551-
});
552-
"
553-
`);
517+
const error = await expectToThrow(code);
518+
expectToContain(String(error), 'RuntimeError: unreachable');
554519
});
555520
});
556521

0 commit comments

Comments
 (0)