Skip to content

Commit

Permalink
Improve error message for nested styled jsx tags
Browse files Browse the repository at this point in the history
  • Loading branch information
hanneslund committed Jan 30, 2022
1 parent 1383612 commit c5c1273
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 2 deletions.
4 changes: 4 additions & 0 deletions errors/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,10 @@
{
"title": "deleting-query-params-in-middlewares",
"path": "/errors/deleting-query-params-in-middlewares.md"
},
{
"title": "nested-styled-jsx-tags",
"path": "/errors/nested-styled-jsx-tags.md"
}
]
}
Expand Down
54 changes: 54 additions & 0 deletions errors/nested-styled-jsx-tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Nested `<style jsx>` tags

#### Why This Error Occurred

You have nested `<style jsx>` tags in a component. `<style jsx>` tags must be at the root of a `styled-jsx` scope.

#### Possible Ways to Fix It

**Before**

```jsx
const Component = () => (
<div>
<p>
Hello world
<style jsx>{`
p {
color: white;
}
`}</style>
</p>
<style global jsx>{`
body {
background: black;
}
`}</style>
</div>
)
```

**After**

```jsx
const Component = () => (
<div>
<p>Hello world</p>
<style jsx>{`
p {
color: white;
}
`}</style>
<style global jsx>{`
body {
background: black;
}
`}</style>
</div>
)
```

### Useful Links

- [Built-In CSS-in-JS](https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js)
- [styled-jsx documentation](https://github.com/vercel/styled-jsx)
24 changes: 22 additions & 2 deletions packages/next-swc/crates/core/src/styled_jsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub fn styled_jsx(cm: Arc<SourceMap>) -> impl Fold {
add_default_decl: Default::default(),
in_function_params: Default::default(),
evaluator: Default::default(),
visiting_styled_jsx_descendants: Default::default(),
}
}

Expand All @@ -65,6 +66,7 @@ struct StyledJSXTransformer {
add_default_decl: Option<(Id, Expr)>,
in_function_params: bool,
evaluator: Option<Evaluator>,
visiting_styled_jsx_descendants: bool,
}

pub struct LocalStyle {
Expand Down Expand Up @@ -95,6 +97,18 @@ enum StyleExpr<'a> {
impl Fold for StyledJSXTransformer {
fn fold_jsx_element(&mut self, el: JSXElement) -> JSXElement {
if is_styled_jsx(&el) {
if self.visiting_styled_jsx_descendants {
HANDLER.with(|handler| {
handler
.struct_span_err(
el.span,
"Detected nested styled-jsx tag.\nRead more: https://nextjs.org/docs/messages/nested-styled-jsx-tag",
)
.emit()
});
return el;
}

let parent_has_styled_jsx = self.has_styled_jsx;
if !parent_has_styled_jsx {
if self.check_for_jsx_styles(Some(&el), &el.children).is_err() {
Expand All @@ -112,7 +126,10 @@ impl Fold for StyledJSXTransformer {
}

if self.has_styled_jsx {
return el.fold_children_with(self);
self.visiting_styled_jsx_descendants = true;
let el = el.fold_children_with(self);
self.visiting_styled_jsx_descendants = false;
return el;
}

if self.check_for_jsx_styles(None, &el.children).is_err() {
Expand All @@ -126,7 +143,10 @@ impl Fold for StyledJSXTransformer {

fn fold_jsx_fragment(&mut self, fragment: JSXFragment) -> JSXFragment {
if self.has_styled_jsx {
return fragment.fold_children_with(self);
self.visiting_styled_jsx_descendants = true;
let fragment = fragment.fold_children_with(self);
self.visiting_styled_jsx_descendants = false;
return fragment;
}

if self.check_for_jsx_styles(None, &fragment.children).is_err() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const Component = () => (
<>
<header>
<Comp>
<style jsx>{styles}</style>
<style jsx global>{``}</style>
</Comp>
<p><style jsx>{``}</style></p>
</header>
<div>
<h1>
Welcome!
<style jsx>{``}</style>
</h1>
<style jsx>{``}</style>
</div>
<div>
<style jsx>{``}</style>
<h1>
Hello world!
<style jsx global>{``}</style>
</h1>
</div>
<div>
<>
<style jsx>{styles}</style>
</>
<style jsx>{``}</style>
</div>
</>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import _JSXStyle from "styled-jsx/style";
const Component = ()=><>
<header >
<Comp >
<_JSXStyle id={styles.__hash}>{styles}</_JSXStyle>
<_JSXStyle id={"b3e1b6a7c9b96113"}>{""}</_JSXStyle>
</Comp>
<p className={"jsx-b3e1b6a7c9b96113"}><_JSXStyle id={"b3e1b6a7c9b96113"}>{""}</_JSXStyle></p>
</header>
<div className={"jsx-b3e1b6a7c9b96113"}>
<h1 className={"jsx-b3e1b6a7c9b96113"}>
Welcome!
<style jsx>{``}</style>
</h1>
<_JSXStyle id={"b3e1b6a7c9b96113"}>{""}</_JSXStyle>
</div>
<div className={"jsx-b3e1b6a7c9b96113"}>
<_JSXStyle id={"b3e1b6a7c9b96113"}>{""}</_JSXStyle>
<h1 className={"jsx-b3e1b6a7c9b96113"}>
Hello world!
<style jsx global>{``}</style>
</h1>
</div>
<div className={"jsx-b3e1b6a7c9b96113"}>
<>
<style jsx>{styles}</style>
</>
<_JSXStyle id={"b3e1b6a7c9b96113"}>{""}</_JSXStyle>
</div>
</>
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error: Detected nested styled-jsx tag.
Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tag
--> input.js:13:9
|
13 | <style jsx>{``}</style>
| ^^^^^^^^^^^^^^^^^^^^^^^

error: Detected nested styled-jsx tag.
Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tag
--> input.js:21:9
|
21 | <style jsx global>{``}</style>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Detected nested styled-jsx tag.
Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tag
--> input.js:26:9
|
26 | <style jsx>{styles}</style>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 comments on commit c5c1273

Please sign in to comment.