From 687e9d85c11ec568df424604ab5eb7070d983d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 17 Nov 2019 22:03:04 +0100 Subject: [PATCH] Fix support for Global transformer with importMap --- .../__fixtures__/global-needs-css.js | 8 +++ .../import-mapping/__fixtures__/global.js | 4 ++ .../__snapshots__/import-mapping.js.snap | 56 +++++++++++++++++ .../import-mapping/import-mapping.js | 3 + .../babel-plugin-emotion/src/core-macro.js | 36 ++++++++--- packages/babel-plugin-emotion/src/index.js | 61 ++++++++++++------- 6 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global-needs-css.js create mode 100644 packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global.js diff --git a/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global-needs-css.js b/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global-needs-css.js new file mode 100644 index 0000000000..0357e18d21 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global-needs-css.js @@ -0,0 +1,8 @@ +import * as React from 'react' +import { SomeGlobalFromCore } from 'package-two' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => ( + +) diff --git a/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global.js b/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global.js new file mode 100644 index 0000000000..71cf49659f --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/import-mapping/__fixtures__/global.js @@ -0,0 +1,4 @@ +import * as React from 'react' +import { SomeGlobalFromCore } from 'package-two' + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/import-mapping/__snapshots__/import-mapping.js.snap b/packages/babel-plugin-emotion/__tests__/import-mapping/__snapshots__/import-mapping.js.snap index 966dd9afdc..0b4d704099 100644 --- a/packages/babel-plugin-emotion/__tests__/import-mapping/__snapshots__/import-mapping.js.snap +++ b/packages/babel-plugin-emotion/__tests__/import-mapping/__snapshots__/import-mapping.js.snap @@ -1,5 +1,61 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`import mapping global 1`] = ` +"import * as React from 'react' +import { SomeGlobalFromCore } from 'package-two' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +function _EMOTION_STRINGIFIED_CSS_ERROR__() { return \\"You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop).\\"; } + +import * as React from 'react'; +import { SomeGlobalFromCore } from 'package-two'; + +var _ref = process.env.NODE_ENV === \\"production\\" ? { + name: \\"1lrxbo5\\", + styles: \\"color:hotpink;\\" +} : { + name: \\"1lrxbo5\\", + styles: \\"color:hotpink;\\", + map: \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImdsb2JhbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHeUMiLCJmaWxlIjoiZ2xvYmFsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBTb21lR2xvYmFsRnJvbUNvcmUgfSBmcm9tICdwYWNrYWdlLXR3bydcblxuZXhwb3J0IGRlZmF1bHQgKCkgPT4gPFNvbWVHbG9iYWxGcm9tQ29yZSBzdHlsZXM9e3sgY29sb3I6ICdob3RwaW5rJyB9fSAvPlxuIl19 */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + +exports[`import mapping global-needs-css 1`] = ` +"import * as React from 'react' +import { SomeGlobalFromCore } from 'package-two' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => ( + +) + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { someCssFromCore as _css } from \\"package-two\\"; +import * as React from 'react'; +import { SomeGlobalFromCore } from 'package-two'; + +const getBgColor = () => ({ + backgroundColor: '#fff' +}); + +export default (() => );" +`; + exports[`import mapping jsx 1`] = ` "/** @jsx someJsx */ import { someJsx } from 'package-two' diff --git a/packages/babel-plugin-emotion/__tests__/import-mapping/import-mapping.js b/packages/babel-plugin-emotion/__tests__/import-mapping/import-mapping.js index c603d914e8..3f9b2cd164 100644 --- a/packages/babel-plugin-emotion/__tests__/import-mapping/import-mapping.js +++ b/packages/babel-plugin-emotion/__tests__/import-mapping/import-mapping.js @@ -18,6 +18,9 @@ babelTester('import mapping', __dirname, { }, someCssFromCore: { canonicalImport: ['@emotion/core', 'css'] + }, + SomeGlobalFromCore: { + canonicalImport: ['@emotion/core', 'Global'] } }, diff --git a/packages/babel-plugin-emotion/src/core-macro.js b/packages/babel-plugin-emotion/src/core-macro.js index 9e55ca91a6..10401029be 100644 --- a/packages/babel-plugin-emotion/src/core-macro.js +++ b/packages/babel-plugin-emotion/src/core-macro.js @@ -37,11 +37,13 @@ export const transformCssCallExpression = ({ export const transformInlineCsslessExpression = ({ state, babel, - path + path, + cssImport = { importSource: '@emotion/core', cssExport: 'css' } }: { babel: *, state: *, - path: * + path: *, + cssImport?: { importSource: string, cssExport: string } }) => { let t = babel.types let expressionPath = path.get('value.expression') @@ -66,12 +68,12 @@ export const transformInlineCsslessExpression = ({ sourceMap }) - const { importSource = '@emotion/core', cssExport = 'css' } = state - if (t.isCallExpression(expressionPath)) { expressionPath .get('callee') - .replaceWith(addImport(state, importSource, cssExport, 'css')) + .replaceWith( + addImport(state, cssImport.importSource, cssImport.cssExport, 'css') + ) } } @@ -87,7 +89,19 @@ let cssTransformer = ({ transformCssCallExpression({ babel, state, path: reference.parentPath }) } -let globalTransformer = ({ state, babel, reference }) => { +let globalTransformer = ({ + state, + babel, + reference, + importSource, + options +}: { + state: any, + babel: any, + reference: any, + importSource: string, + options: { cssExport?: string } +}) => { const t = babel.types if ( @@ -110,7 +124,15 @@ let globalTransformer = ({ state, babel, reference }) => { (t.isObjectExpression(stylesPropPath.node.value.expression) || t.isArrayExpression(stylesPropPath.node.value.expression)) ) { - transformInlineCsslessExpression({ state, babel, path: stylesPropPath }) + transformInlineCsslessExpression({ + state, + babel, + path: stylesPropPath, + cssImport: options.cssExport !== undefined && { + importSource, + cssExport: options.cssExport + } + }) } } diff --git a/packages/babel-plugin-emotion/src/index.js b/packages/babel-plugin-emotion/src/index.js index dd85d76f66..623253053a 100644 --- a/packages/babel-plugin-emotion/src/index.js +++ b/packages/babel-plugin-emotion/src/index.js @@ -11,6 +11,21 @@ import coreMacro, { } from './core-macro' import { getStyledOptions, createTransformerMacro } from './utils' +const getCssExport = (reexported, importSource, mapping) => { + const cssExport = Object.keys(mapping).find(localExportName => { + const [packageName, exportName] = mapping[localExportName].canonicalImport + return packageName === '@emotion/core' && exportName === 'css' + }) + + if (!cssExport) { + throw new Error( + `You have specified that '${importSource}' re-exports '${reexported}' from '@emotion/core' but it doesn't also re-export 'css' from '@emotion/core', 'css' is necessary for certain optimisations, please re-export it from '${importSource}'` + ) + } + + return cssExport +} + let webStyledMacro = createStyledMacro({ importSource: '@emotion/styled/base', originalImportSource: '@emotion/styled', @@ -122,7 +137,7 @@ export default function(babel: *) { let jsxCoreImports: Array<{ importSource: string, export: string, - cssExport: string | null + cssExport: string }> = [ { importSource: '@emotion/core', export: 'jsx', cssExport: 'css' } ] @@ -137,7 +152,7 @@ export default function(babel: *) { jsxCoreImports.push({ importSource, export: localExportName, - cssExport: null + cssExport: getCssExport('jsx', importSource, value) }) return } @@ -149,6 +164,22 @@ export default function(babel: *) { ) } + let extraOptions + + if (packageName === '@emotion/core' && exportName === 'Global') { + // this option is not supposed to be set in importMap + extraOptions = { + cssExport: getCssExport('Global', importSource, value) + } + } else if ( + packageName === '@emotion/styled' && + exportName === 'default' + ) { + // this is supposed to override defaultOptions value + // and let correct value to be set if coming in options + extraOptions = { styledBaseImport: undefined } + } + let [exportTransformer, defaultOptions] = // $FlowFixMe Array.isArray(packageTransformers[exportName]) @@ -157,30 +188,13 @@ export default function(babel: *) { transformers[localExportName] = [ exportTransformer, - { ...defaultOptions, styledBaseImport: undefined, ...options } + { ...defaultOptions, ...extraOptions, ...options } ] }) macros[importSource] = createTransformerMacro(transformers, { importSource }) }) - jsxCoreImports.forEach(jsxCoreImport => { - if (jsxCoreImport.importSource === '@emotion/core') return - let { transformers } = macros[jsxCoreImport.importSource] - for (let key in transformers) { - if (transformers[key][0] === coreTransformers.css) { - jsxCoreImport.cssExport = key - return - } - } - throw new Error( - `You have specified that '${ - jsxCoreImport.importSource - }' re-exports 'jsx' from '@emotion/core' but it doesn't also re-export 'css' from '@emotion/core', 'css' is necessary for certain optimisations, please re-export it from '${ - jsxCoreImport.importSource - }'` - ) - }) state.pluginMacros = { '@emotion/styled': webStyledMacro, '@emotion/core': coreMacro, @@ -227,7 +241,12 @@ export default function(babel: *) { (t.isObjectExpression(path.node.value.expression) || t.isArrayExpression(path.node.value.expression)) ) { - transformInlineCsslessExpression({ state, babel, path }) + transformInlineCsslessExpression({ + state, + babel, + path, + cssImport: state.jsxCoreImport + }) } }, CallExpression: {