next-swc: Improve error message for nested styled jsx tags (#33805)

Before
![image](https://user-images.githubusercontent.com/25056922/151694166-a27a35b6-5fb4-4179-8c88-bd98ede35fea.png)

After
![image](https://user-images.githubusercontent.com/25056922/151758033-65576e5b-e2e8-435d-87b3-9e384b13936b.png)


Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
This commit is contained in:
Hannes Bornö 2022-05-23 00:45:58 +02:00 committed by GitHub
parent 78bdbbed1c
commit 318664562c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 163 additions and 2 deletions

View file

@ -658,6 +658,10 @@
"title": "invalid-script", "title": "invalid-script",
"path": "/errors/invalid-script.md" "path": "/errors/invalid-script.md"
}, },
{
"title": "nested-styled-jsx-tags",
"path": "/errors/nested-styled-jsx-tags.md"
},
{ {
"title": "returning-response-body-in-middleware", "title": "returning-response-body-in-middleware",
"path": "/errors/returning-response-body-in-middleware.md" "path": "/errors/returning-response-body-in-middleware.md"

View file

@ -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)

View file

@ -48,6 +48,7 @@ pub fn styled_jsx(cm: Arc<SourceMap>, file_name: FileName) -> impl Fold {
add_default_decl: Default::default(), add_default_decl: Default::default(),
in_function_params: Default::default(), in_function_params: Default::default(),
evaluator: Default::default(), evaluator: Default::default(),
visiting_styled_jsx_descendants: Default::default(),
} }
} }
@ -70,6 +71,7 @@ struct StyledJSXTransformer {
add_default_decl: Option<(Id, Expr)>, add_default_decl: Option<(Id, Expr)>,
in_function_params: bool, in_function_params: bool,
evaluator: Option<Evaluator>, evaluator: Option<Evaluator>,
visiting_styled_jsx_descendants: bool,
} }
pub struct LocalStyle { pub struct LocalStyle {
@ -101,6 +103,18 @@ enum StyleExpr<'a> {
impl Fold for StyledJSXTransformer { impl Fold for StyledJSXTransformer {
fn fold_jsx_element(&mut self, el: JSXElement) -> JSXElement { fn fold_jsx_element(&mut self, el: JSXElement) -> JSXElement {
if is_styled_jsx(&el) { 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-tags",
)
.emit()
});
return el;
}
let parent_has_styled_jsx = self.has_styled_jsx; let parent_has_styled_jsx = self.has_styled_jsx;
if !parent_has_styled_jsx && self.check_for_jsx_styles(Some(&el), &el.children).is_err() if !parent_has_styled_jsx && self.check_for_jsx_styles(Some(&el), &el.children).is_err()
{ {
@ -117,7 +131,10 @@ impl Fold for StyledJSXTransformer {
} }
if self.has_styled_jsx { 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() { if self.check_for_jsx_styles(None, &el.children).is_err() {
@ -131,7 +148,10 @@ impl Fold for StyledJSXTransformer {
fn fold_jsx_fragment(&mut self, fragment: JSXFragment) -> JSXFragment { fn fold_jsx_fragment(&mut self, fragment: JSXFragment) -> JSXFragment {
if self.has_styled_jsx { 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() { if self.check_for_jsx_styles(None, &fragment.children).is_err() {

View file

@ -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>
</>
)

View file

@ -0,0 +1,31 @@
import _JSXStyle from "next/dist/shared/lib/styled-jsx";
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>
</>
;

View file

@ -0,0 +1,21 @@
x Detected nested styled-jsx tag.
| Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tags
,-[input.js:13:9]
13 | <style jsx>{``}</style>
: ^^^^^^^^^^^^^^^^^^^^^^^
`----
x Detected nested styled-jsx tag.
| Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tags
,-[input.js:21:9]
21 | <style jsx global>{``}</style>
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`----
x Detected nested styled-jsx tag.
| Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tags
,-[input.js:26:9]
26 | <style jsx>{styles}</style>
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^
`----