Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: _JSXStyle import is not found #724

Merged
merged 4 commits into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions src/_utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'path'
import { addDefault } from '@babel/helper-module-imports';
import { addDefault } from '@babel/helper-module-imports'
import * as t from '@babel/types'
import _hashString from 'string-hash'
import { SourceMapGenerator } from 'source-map'
Expand All @@ -9,8 +9,8 @@ import transform from './lib/style-transform'
import {
STYLE_ATTRIBUTE,
GLOBAL_ATTRIBUTE,
STYLE_COMPONENT_ID,
STYLE_COMPONENT,
STYLE_COMPONENT_ID,
STYLE_COMPONENT_DYNAMIC
} from './_constants'

Expand Down Expand Up @@ -258,7 +258,11 @@ export const getJSXStyleInfo = (expr, scope) => {
}
}

export const computeClassNames = (styles, externalJsxId) => {
export const computeClassNames = (
styles,
externalJsxId,
styleComponentImportName
) => {
if (styles.length === 0) {
return {
className: externalJsxId
Expand Down Expand Up @@ -297,7 +301,10 @@ export const computeClassNames = (styles, externalJsxId) => {
// _JSXStyle.dynamic([ ['1234', [props.foo, bar, fn(props)]], ... ])
const dynamic = t.callExpression(
// Callee: _JSXStyle.dynamic
t.memberExpression(t.identifier(STYLE_COMPONENT), t.identifier('dynamic')),
t.memberExpression(
t.identifier(styleComponentImportName),
t.identifier(STYLE_COMPONENT_DYNAMIC)
),
// Arguments
[
t.arrayExpression(
Expand Down Expand Up @@ -380,7 +387,12 @@ export const cssToBabelType = css => {
return t.cloneDeep(css)
}

export const makeStyledJsxTag = (id, transformedCss, expressions = []) => {
export const makeStyledJsxTag = (
id,
transformedCss,
expressions = [],
styleComponentImportName
) => {
const css = cssToBabelType(transformedCss)

const attributes = [
Expand All @@ -402,8 +414,8 @@ export const makeStyledJsxTag = (id, transformedCss, expressions = []) => {
}

return t.jSXElement(
t.jSXOpeningElement(t.jSXIdentifier(STYLE_COMPONENT), attributes),
t.jSXClosingElement(t.jSXIdentifier(STYLE_COMPONENT)),
t.jSXOpeningElement(t.jSXIdentifier(styleComponentImportName), attributes),
t.jSXClosingElement(t.jSXIdentifier(styleComponentImportName)),
[t.jSXExpressionContainer(css)]
)
}
Expand Down Expand Up @@ -622,13 +634,9 @@ export const booleanOption = opts => {
}

export const createReactComponentImportDeclaration = state => {
addDefault(
state.file.path,
typeof state.opts.styleModule === 'string'
? state.opts.styleModule
: 'styled-jsx/style',
{ nameHint: STYLE_COMPONENT}
)
return addDefault(state.file.path, state.styleModule, {
nameHint: STYLE_COMPONENT
}).name
}

export const setStateOptions = state => {
Expand All @@ -650,6 +658,10 @@ export const setStateOptions = state => {
vendorPrefixes: state.opts.vendorPrefixes
})
}
state.styleModule =
typeof state.opts.styleModule === 'string'
? state.opts.styleModule
: 'styled-jsx/style'
giuseppeg marked this conversation as resolved.
Show resolved Hide resolved
}

export function log(message) {
Expand Down
29 changes: 15 additions & 14 deletions src/babel-external.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as t from '@babel/types'

import { STYLE_COMPONENT } from './_constants'

import {
getJSXStyleInfo,
processCss,
Expand All @@ -10,7 +8,6 @@ import {
getScope,
computeClassNames,
makeStyledJsxTag,
createReactComponentImportDeclaration,
setStateOptions
} from './_utils'

Expand All @@ -23,7 +20,8 @@ export function processTaggedTemplateExpression({
splitRules,
plugins,
vendorPrefixes,
sourceMaps
sourceMaps,
styleComponentImportName
}) {
const templateLiteral = path.get('quasi')
let scope
Expand All @@ -39,7 +37,11 @@ export function processTaggedTemplateExpression({

const stylesInfo = getJSXStyleInfo(templateLiteral, scope)

const { staticClassName, className } = computeClassNames([stylesInfo])
const { staticClassName, className } = computeClassNames(
[stylesInfo],
undefined,
styleComponentImportName
)

const styles = processCss(
{
Expand All @@ -64,7 +66,7 @@ export function processTaggedTemplateExpression({
t.objectExpression([
t.objectProperty(
t.identifier('styles'),
makeStyledJsxTag(hash, css, expressions)
makeStyledJsxTag(hash, css, expressions, styleComponentImportName)
),
t.objectProperty(t.identifier('className'), className)
])
Expand Down Expand Up @@ -212,21 +214,20 @@ export const visitor = {
: process.env.NODE_ENV === 'production',
plugins: state.plugins,
vendorPrefixes,
sourceMaps
sourceMaps,
styleComponentImportName: state.styleComponentImportName
})
})
)

// When using the `resolve` helper we need to add an import
// for the _JSXStyle component `styled-jsx/style`
if (
hasJSXStyle &&
taggedTemplateExpressions.resolve.length > 0 &&
!state.hasInjectedJSXStyle &&
!path.scope.hasBinding(STYLE_COMPONENT)
) {
const useResolve =
hasJSXStyle && taggedTemplateExpressions.resolve.length > 0

if (useResolve) {
state.file.hasCssResolve = true
state.hasInjectedJSXStyle = true
createReactComponentImportDeclaration(state)
}
})

Expand Down
45 changes: 34 additions & 11 deletions src/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import {
setStateOptions
} from './_utils'

import { STYLE_COMPONENT } from './_constants'

export default function({ types: t }) {
const jsxVisitors = {
JSXOpeningElement(path, state) {
Expand All @@ -43,7 +41,7 @@ export default function({ types: t }) {
if (
name &&
name !== 'style' &&
name !== STYLE_COMPONENT &&
name !== state.styleComponentImportName &&
(name.charAt(0) !== name.charAt(0).toUpperCase() ||
Object.values(path.scope.bindings).some(binding =>
binding.referencePaths.some(r => r === tag)
Expand Down Expand Up @@ -172,7 +170,8 @@ export default function({ types: t }) {
if (state.styles.length > 0 || externalJsxId) {
const { staticClassName, className } = computeClassNames(
state.styles,
externalJsxId
externalJsxId,
state.styleComponentImportName
)
state.className = className
state.staticClassName = staticClassName
Expand Down Expand Up @@ -224,7 +223,9 @@ export default function({ types: t }) {
) {
const [id, css] = state.externalStyles.shift()

path.replaceWith(makeStyledJsxTag(id, css))
path.replaceWith(
makeStyledJsxTag(id, css, [], state.styleComponentImportName)
)
return
}

Expand All @@ -247,7 +248,14 @@ export default function({ types: t }) {
splitRules
})

path.replaceWith(makeStyledJsxTag(hash, css, expressions))
path.replaceWith(
makeStyledJsxTag(
hash,
css,
expressions,
state.styleComponentImportName
)
)
}
}
}
Expand Down Expand Up @@ -283,9 +291,14 @@ export default function({ types: t }) {
state.hasJSXStyle = null
state.ignoreClosing = null
state.file.hasJSXStyle = false

state.file.hasCssResolve = false
setStateOptions(state)

// `addDefault` will generate unique id for the scope
state.styleComponentImportName = createReactComponentImportDeclaration(
state
)
giuseppeg marked this conversation as resolved.
Show resolved Hide resolved

// we need to beat the arrow function transform and
// possibly others so we traverse from here or else
// dynamic values in classNames could be incorrect
Expand All @@ -294,19 +307,29 @@ export default function({ types: t }) {
// Transpile external styles
path.traverse(externalStylesVisitor, state)
},
exit({ scope }, state) {
exit(path, state) {
// For source that didn't really need styled-jsx/style imports,
// remove the injected import at the beginning
if (!state.file.hasJSXStyle && !state.file.hasCssResolve) {
path.traverse({
ImportDeclaration(importPath) {
if (importPath.node.source.value === state.styleModule) {
importPath.remove()
}
}
huozhi marked this conversation as resolved.
Show resolved Hide resolved
})
}

if (
!(
state.file.hasJSXStyle &&
!state.hasInjectedJSXStyle &&
!scope.hasBinding(STYLE_COMPONENT)
!path.scope.hasBinding(state.styleComponentImportName)
)
) {
return
}

state.hasInjectedJSXStyle = true
createReactComponentImportDeclaration(state)
giuseppeg marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
11 changes: 4 additions & 7 deletions src/macro.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {
setStateOptions,
createReactComponentImportDeclaration
} from './_utils'
import { STYLE_COMPONENT } from './_constants'

export default createMacro(styledJsxMacro)

function styledJsxMacro({ references, state }) {
setStateOptions(state)
state.styleComponentImportName = createReactComponentImportDeclaration(state)

// Holds a reference to all the lines where strings are tagged using the `css` tag name.
// We print a warning at the end of the macro in case there is any reference to css,
Expand Down Expand Up @@ -94,15 +94,12 @@ function styledJsxMacro({ references, state }) {
: process.env.NODE_ENV === 'production',
plugins: state.plugins,
vendorPrefixes: state.opts.vendorPrefixes,
sourceMaps: state.opts.sourceMaps
sourceMaps: state.opts.sourceMaps,
styleComponentImportName: state.styleComponentImportName
})

if (
!state.hasInjectedJSXStyle &&
!path.scope.hasBinding(STYLE_COMPONENT)
) {
if (!state.hasInjectedJSXStyle) {
state.hasInjectedJSXStyle = true
createReactComponentImportDeclaration(state)
}
})
})
Expand Down
2 changes: 0 additions & 2 deletions test/babel6/snapshots/index.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,12 @@ Generated by [AVA](https://ava.li).

`import _JSXStyle from "styled-jsx/style";␊
export default class {␊
render() {␊
return <div className={"jsx-2101845350"}>␊
<p className={"jsx-2101845350"}>test</p>␊
<_JSXStyle id={"2101845350"}>{"p.jsx-2101845350{color:red;}"}</_JSXStyle>␊
</div>;␊
}␊
}`

## works with css tagged template literals in the same file
Expand Down
Binary file modified test/babel6/snapshots/index.js.snap
Binary file not shown.
Binary file modified test/babel6/snapshots/plugins.js.snap
Binary file not shown.
4 changes: 1 addition & 3 deletions test/fixtures/class.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export default class {

render () {
render() {
return (
<div>
<p>test</p>
Expand All @@ -12,5 +11,4 @@ export default class {
</div>
)
}

}
13 changes: 13 additions & 0 deletions test/fixtures/conflicts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const _JSXStyle = '_JSXStyle-literal'
export default function() {
return (
<div>
<p>test</p>
<style jsx>{`
p {
color: red;
}
`}</style>
</div>
)
}
5 changes: 5 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ test('works with dynamic element in class', async t => {
t.snapshot(code)
})

test('works with existing identifier for _JSXStyle', async t => {
const { code } = await transform('./fixtures/conflicts.js')
t.snapshot(code)
})

test('does not transpile nested style tags', async t => {
const { message } = await t.throwsAsync(() =>
transform('./fixtures/nested-style-tags.js')
Expand Down
Binary file modified test/snapshots/external.js.snap
Binary file not shown.
13 changes: 13 additions & 0 deletions test/snapshots/index.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@ Generated by [AVA](https://ava.li).
};`

## works with existing identifier for \_JSXStyle

> Snapshot 1

`import _JSXStyle2 from "styled-jsx/style";␊
export const _JSXStyle = '_JSXStyle-literal';␊
export default function () {␊
return <div className={"jsx-319553417"}>␊
<p className={"jsx-319553417"}>test</p>␊
<_JSXStyle2 id={"319553417"}>{"p.jsx-319553417{color:red;}"}</_JSXStyle2>␊
</div>;␊
}`

## works with expressions in template literals

> Snapshot 1
Expand Down
Binary file modified test/snapshots/index.js.snap
Binary file not shown.
Binary file modified test/snapshots/plugins.js.snap
Binary file not shown.