Skip to content

Commit

Permalink
refactor: replace import helper (#726)
Browse files Browse the repository at this point in the history
* enhance: use raw imports injection

* rm cjs test

* remove import path if unused

* fix lint

* let cjs plugin handle imports

* update snapshots

* more test as example

* only inject at exit
  • Loading branch information
huozhi authored Aug 5, 2021
1 parent 2370992 commit de67aea
Show file tree
Hide file tree
Showing 18 changed files with 91 additions and 74 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
}
},
"dependencies": {
"@babel/helper-module-imports": "7.12.5",
"@babel/types": "7.8.3",
"babel-plugin-syntax-jsx": "6.18.0",
"convert-source-map": "1.7.0",
Expand Down
9 changes: 4 additions & 5 deletions src/_utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import path from 'path'
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,7 +8,6 @@ import transform from './lib/style-transform'
import {
STYLE_ATTRIBUTE,
GLOBAL_ATTRIBUTE,
STYLE_COMPONENT,
STYLE_COMPONENT_ID,
STYLE_COMPONENT_DYNAMIC
} from './_constants'
Expand Down Expand Up @@ -634,9 +632,10 @@ export const booleanOption = opts => {
}

export const createReactComponentImportDeclaration = state => {
return addDefault(state.file.path, state.styleModule, {
nameHint: STYLE_COMPONENT
}).name
return t.importDeclaration(
[t.importDefaultSpecifier(t.identifier(state.styleComponentImportName))],
t.stringLiteral(state.styleModule)
)
}

export const setStateOptions = state => {
Expand Down
9 changes: 4 additions & 5 deletions src/babel-external.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,13 @@ export const visitor = {
})
)

// When using the `resolve` helper we need to add an import
// for the _JSXStyle component `styled-jsx/style`
const useResolve =
const hasCssResolve =
hasJSXStyle && taggedTemplateExpressions.resolve.length > 0

if (useResolve) {
// When using the `resolve` helper we need to add an import
// for the _JSXStyle component `styled-jsx/style`
if (hasCssResolve) {
state.file.hasCssResolve = true
state.hasInjectedJSXStyle = true
}
})

Expand Down
34 changes: 9 additions & 25 deletions src/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
createReactComponentImportDeclaration,
setStateOptions
} from './_utils'
import { STYLE_COMPONENT } from './_constants'

export default function({ types: t }) {
const jsxVisitors = {
Expand Down Expand Up @@ -288,16 +289,15 @@ export default function({ types: t }) {
visitor: {
Program: {
enter(path, state) {
setStateOptions(state)
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
)
// create unique identifier for _JSXStyle component
state.styleComponentImportName = path.scope.generateUidIdentifier(
STYLE_COMPONENT
).name

// we need to beat the arrow function transform and
// possibly others so we traverse from here or else
Expand All @@ -308,28 +308,12 @@ export default function({ types: t }) {
path.traverse(externalStylesVisitor, 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()
}
}
})
}

if (
!(
state.file.hasJSXStyle &&
!state.hasInjectedJSXStyle &&
!path.scope.hasBinding(state.styleComponentImportName)
)
) {
return
}
state.hasInjectedJSXStyle = true
state.file.hasJSXStyle = true
const importDeclaration = createReactComponentImportDeclaration(state)
path.unshiftContainer('body', importDeclaration)
}
}
}
Expand Down
15 changes: 10 additions & 5 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 @@ -83,6 +83,15 @@ function styledJsxMacro({ references, state }) {
}
}

if (!state.styleComponentImportName) {
const programPath = path.findParent(p => p.isProgram())
state.styleComponentImportName = programPath.scope.generateUidIdentifier(
STYLE_COMPONENT
).name
const importDeclaration = createReactComponentImportDeclaration(state)
programPath.unshiftContainer('body', importDeclaration)
}

// Finally transform the path :)
processTaggedTemplateExpression({
type: 'resolve',
Expand All @@ -97,10 +106,6 @@ function styledJsxMacro({ references, state }) {
sourceMaps: state.opts.sourceMaps,
styleComponentImportName: state.styleComponentImportName
})

if (!state.hasInjectedJSXStyle) {
state.hasInjectedJSXStyle = true
}
})
})

Expand Down
5 changes: 2 additions & 3 deletions test/babel6/snapshots/attribute.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,9 @@ Generated by [AVA](https://ava.li).

> Snapshot 1
`import _JSXStyle from "styled-jsx/style";␊
var _this = this;␊
`var _this = this;␊
import _JSXStyle from "styled-jsx/style";␊
export default (() => {␊
const Element = 'div';␊
return <div className={"jsx-2886504620"}>␊
Expand Down
Binary file modified test/babel6/snapshots/attribute.js.snap
Binary file not shown.
Binary file modified test/babel6/snapshots/external.js.snap
Binary file not shown.
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.
7 changes: 0 additions & 7 deletions test/fixtures/cjs-module.js

This file was deleted.

35 changes: 27 additions & 8 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import ReactDOM from 'react-dom/server'

// Ours
import plugin from '../src/babel'
import _transform from './_transform'
import _transform, { transformSource as _transformSource } from './_transform'

const transform = (file, opts = {}) =>
_transform(file, {
plugins: [plugin],
...opts
})

const transformSource = (src, opts = {}) =>
_transformSource(src.trim(), {
plugins: [[plugin, opts]],
...opts
})

test('handles dynamic `this` value inside of arrow function', async t => {
const { code } = await transform(
'./fixtures/dynamic-this-value-in-arrow.js',
Expand All @@ -28,13 +34,6 @@ test('works with stateless', async t => {
t.snapshot(code)
})

test('works with a CJS module', async t => {
const { code } = await transform('./fixtures/cjs-module.js', {
sourceType: 'script'
})
t.snapshot(code)
})

test('works with fragment', async t => {
const { code } = await transform('./fixtures/fragment.js')
t.snapshot(code)
Expand Down Expand Up @@ -124,6 +123,26 @@ test('does not transpile nested style tags', async t => {
t.regex(message, /detected nested style tag/i)
})

test('works with exported jsx-style (CommonJS modules)', async t => {
const { code } = await transformSource(
'module.exports = () => <p><style jsx>{`p { color:red; }`}</style></p>',
{
plugins: [plugin, '@babel/plugin-transform-modules-commonjs']
}
)
t.snapshot(code)
})

test('works with exported non-jsx style (CommonJS modules)', async t => {
const { code } = await transformSource(
'module.exports = () => <p><style>{`p { color:red; }`}</style></p>',
{
plugins: [plugin, '@babel/plugin-transform-modules-commonjs']
}
)
t.snapshot(code)
})

function clearModulesCache() {
;['../src/lib/stylesheet', '../src/style', '../src/server'].forEach(
moduleName => {
Expand Down
Binary file modified test/snapshots/attribute.js.snap
Binary file not shown.
Binary file modified test/snapshots/external.js.snap
Binary file not shown.
48 changes: 34 additions & 14 deletions test/snapshots/index.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,6 @@ Generated by [AVA](https://ava.li).
<_JSXStyle id={"2529315885"}>{"span.jsx-2529315885{color:red;}"}</_JSXStyle>␊
</div>;`

## works with a CJS module

> Snapshot 1
`'use strict';␊
var _JSXStyle = _interopRequireDefault(require("styled-jsx/style")).default;␊
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }␊
module.exports = () => <div className={"jsx-2886504620"}>␊
<_JSXStyle id={"2886504620"}>{"div.jsx-2886504620{color:red;}"}</_JSXStyle>␊
</div>;`

## works with class

> Snapshot 1
Expand Down Expand Up @@ -335,6 +321,20 @@ Generated by [AVA](https://ava.li).
const Test2 = () => <_JSXStyle id={"2743241663"}>{"p{color:red;}"}</_JSXStyle>;`

## works with module.exports component (CommonJS modules)

> Snapshot 1
`"use strict";␊
var _style = _interopRequireDefault(require("styled-jsx/style"));␊
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }␊
module.exports = () => <p className={"jsx-2982525546"}>␊
<_style.default id={"2982525546"}>{"p.jsx-2982525546{color:red;}"}</_style.default>␊
</p>;`

## works with multiple jsx blocks

> Snapshot 1
Expand Down Expand Up @@ -391,3 +391,23 @@ Generated by [AVA](https://ava.li).
<p className={"jsx-2743241663"}>woot</p>␊
<_JSXStyle id={"2743241663"}>{"p.jsx-2743241663{color:red;}"}</_JSXStyle>␊
</div>);`

## works with exported jsx-style (CommonJS modules)

> Snapshot 1
`"use strict";␊
var _style = _interopRequireDefault(require("styled-jsx/style"));␊
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }␊
module.exports = () => <p className={"jsx-3800097675"}><_style.default id={"3800097675"}>{"p.jsx-3800097675{color:red;}"}</_style.default></p>;`

## works with exported non-jsx style (CommonJS modules)

> Snapshot 1
`"use strict";␊
module.exports = () => <p><style>{`p { color:red; }`}</style></p>;`
Binary file modified test/snapshots/index.js.snap
Binary file not shown.
Binary file modified test/snapshots/plugins.js.snap
Binary file not shown.
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@
dependencies:
"@babel/types" "^7.12.1"

"@babel/helper-module-imports@7.12.5", "@babel/helper-module-imports@^7.12.1":
"@babel/helper-module-imports@^7.12.1":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb"
integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==
Expand Down

0 comments on commit de67aea

Please sign in to comment.