From 3ff829b03379e1330535f36d5a15d778b258e786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 18 Nov 2019 00:38:12 +0100 Subject: [PATCH] Handle `Global` with Babel (#1639) * Handle `Global` with Babel * Fix support for Global transformer with importMap * Split changesets --- .changeset/moody-stingrays-sort.md | 5 + .changeset/two-kiwis-give.md | 5 + .../global-requires-options.js.snap | 20 ++ .../__tests__/__snapshots__/global.js.snap | 206 ++++++++++++++++++ .../global-macro/__fixtures__/basic-array.js | 6 + .../global-macro/__fixtures__/basic-obj.js | 4 + .../__fixtures__/complex-array.js | 6 + .../global-macro/__fixtures__/complex-obj.js | 6 + .../__fixtures__/css-used-as-value.js | 5 + .../global-macro/__fixtures__/no-jsx.js | 4 + .../__fixtures__/no-styles-prop.js | 4 + .../__fixtures__/spread-styles.js | 5 + .../__fixtures__/with-closing-element.js | 6 + .../global-macro/__snapshots__/index.js.snap | 206 ++++++++++++++++++ .../__tests__/global-macro/index.js | 4 + .../__tests__/global-requires-options.js | 17 ++ .../babel-plugin-emotion/__tests__/global.js | 12 + .../__fixtures__/global-needs-css.js | 8 + .../import-mapping/__fixtures__/global.js | 4 + .../__snapshots__/import-mapping.js.snap | 56 +++++ .../import-mapping/import-mapping.js | 3 + .../__fixtures__/global-styles-prop.js | 4 + .../source-maps/__snapshots__/index.js.snap | 27 +++ .../babel-plugin-emotion/src/core-macro.js | 125 ++++++++++- packages/babel-plugin-emotion/src/index.js | 109 ++++----- 25 files changed, 782 insertions(+), 75 deletions(-) create mode 100644 .changeset/moody-stingrays-sort.md create mode 100644 .changeset/two-kiwis-give.md create mode 100644 packages/babel-plugin-emotion/__tests__/__snapshots__/global-requires-options.js.snap create mode 100644 packages/babel-plugin-emotion/__tests__/__snapshots__/global.js.snap create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-array.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-obj.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-array.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-obj.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/css-used-as-value.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-jsx.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-styles-prop.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/spread-styles.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/with-closing-element.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/__snapshots__/index.js.snap create mode 100644 packages/babel-plugin-emotion/__tests__/global-macro/index.js create mode 100644 packages/babel-plugin-emotion/__tests__/global-requires-options.js create mode 100644 packages/babel-plugin-emotion/__tests__/global.js 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 create mode 100644 packages/babel-plugin-emotion/__tests__/source-maps/__fixtures__/global-styles-prop.js diff --git a/.changeset/moody-stingrays-sort.md b/.changeset/moody-stingrays-sort.md new file mode 100644 index 0000000000..c36050960d --- /dev/null +++ b/.changeset/moody-stingrays-sort.md @@ -0,0 +1,5 @@ +--- +'@emotion/core': minor +--- + +`Global` imported from macro entry (`@emotion/core/macro`) gets source maps generated now when inline css-less expression is used as value of the `styles` prop. diff --git a/.changeset/two-kiwis-give.md b/.changeset/two-kiwis-give.md new file mode 100644 index 0000000000..2f4eaa3c84 --- /dev/null +++ b/.changeset/two-kiwis-give.md @@ -0,0 +1,5 @@ +--- +'babel-plugin-emotion': minor +--- + +`Global` gets handled by the Babel plugin now - this gives inline css-less expressions source maps. diff --git a/packages/babel-plugin-emotion/__tests__/__snapshots__/global-requires-options.js.snap b/packages/babel-plugin-emotion/__tests__/__snapshots__/global-requires-options.js.snap new file mode 100644 index 0000000000..6789885a13 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/__snapshots__/global-requires-options.js.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Global inline source maps can be disabled 1`] = ` +" +import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import * as React from 'react'; +import { Global } from '@emotion/core'; +var _ref = { + name: \\"1lrxbo5\\", + styles: \\"color:hotpink;\\" +}; +export default (() => );" +`; diff --git a/packages/babel-plugin-emotion/__tests__/__snapshots__/global.js.snap b/packages/babel-plugin-emotion/__tests__/__snapshots__/global.js.snap new file mode 100644 index 0000000000..ecbad5a652 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/__snapshots__/global.js.snap @@ -0,0 +1,206 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`emotion-babel-plugin Global basic-array 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => ( + +) + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from '@emotion/core'; +export default (() => );" +`; + +exports[`emotion-babel-plugin Global basic-obj 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +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 { Global } from '@emotion/core'; + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImJhc2ljLW9iai5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHNkIiLCJmaWxlIjoiYmFzaWMtb2JqLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBHbG9iYWwgfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5leHBvcnQgZGVmYXVsdCAoKSA9PiA8R2xvYmFsIHN0eWxlcz17eyBjb2xvcjogJ2hvdHBpbmsnIH19IC8+XG4iXX0= */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + +exports[`emotion-babel-plugin Global complex-array 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from '@emotion/core'; + +const getBgColor = () => ({ + backgroundColor: '#fff' +}); + +export default (() => );" +`; + +exports[`emotion-babel-plugin Global complex-obj 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from '@emotion/core'; + +const getBgColor = () => ({ + backgroundColor: '#fff' +}); + +export default (() => );" +`; + +exports[`emotion-babel-plugin Global css-used-as-value 1`] = ` +"import * as React from 'react' +import { Global, css } from '@emotion/core' + +// this gets ignored by Global macro, but it tests that this combination doesn't crash or something +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 { Global, css } from '@emotion/core'; // this gets ignored by Global macro, but it tests that this combination doesn't crash or something + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNzcy11c2VkLWFzLXZhbHVlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlxQyIsImZpbGUiOiJjc3MtdXNlZC1hcy12YWx1ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgR2xvYmFsLCBjc3MgfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG4vLyB0aGlzIGdldHMgaWdub3JlZCBieSBHbG9iYWwgbWFjcm8sIGJ1dCBpdCB0ZXN0cyB0aGF0IHRoaXMgY29tYmluYXRpb24gZG9lc24ndCBjcmFzaCBvciBzb21ldGhpbmdcbmV4cG9ydCBkZWZhdWx0ICgpID0+IDxHbG9iYWwgc3R5bGVzPXtjc3MoeyBjb2xvcjogJ2hvdHBpbmsnIH0pfSAvPlxuIl19 */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + +exports[`emotion-babel-plugin Global no-jsx 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +const foo = Global + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import * as React from 'react'; +import { Global } from '@emotion/core'; +const foo = Global;" +`; + +exports[`emotion-babel-plugin Global no-styles-prop 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import * as React from 'react'; +import { Global } from '@emotion/core'; +export default (() => );" +`; + +exports[`emotion-babel-plugin Global spread-styles 1`] = ` +"/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +/* eslint-disable */ +import * as React from 'react'; +import { Global } from '@emotion/core'; +export default (() => );" +`; + +exports[`emotion-babel-plugin Global with-closing-element 1`] = ` +"/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core' + +// prettier-ignore +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).\\"; } + +/* eslint-disable */ +import * as React from 'react'; +import { Global } from '@emotion/core'; // prettier-ignore + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndpdGgtY2xvc2luZy1lbGVtZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUs2QiIsImZpbGUiOiJ3aXRoLWNsb3NpbmctZWxlbWVudC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlICovXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IEdsb2JhbCB9IGZyb20gJ0BlbW90aW9uL2NvcmUnXG5cbi8vIHByZXR0aWVyLWlnbm9yZVxuZXhwb3J0IGRlZmF1bHQgKCkgPT4gPEdsb2JhbCBzdHlsZXM9e3sgY29sb3I6ICdob3RwaW5rJyB9fT48L0dsb2JhbD5cbiJdfQ== */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-array.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-array.js new file mode 100644 index 0000000000..53777c61e3 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-array.js @@ -0,0 +1,6 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => ( + +) diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-obj.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-obj.js new file mode 100644 index 0000000000..873f79424a --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/basic-obj.js @@ -0,0 +1,4 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-array.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-array.js new file mode 100644 index 0000000000..df86dfb3df --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-array.js @@ -0,0 +1,6 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-obj.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-obj.js new file mode 100644 index 0000000000..e0b355380f --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/complex-obj.js @@ -0,0 +1,6 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/css-used-as-value.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/css-used-as-value.js new file mode 100644 index 0000000000..d81888e8f9 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/css-used-as-value.js @@ -0,0 +1,5 @@ +import * as React from 'react' +import { Global, css } from '@emotion/core/macro' + +// this gets ignored by Global macro, but it tests that this combination doesn't crash or something +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-jsx.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-jsx.js new file mode 100644 index 0000000000..b9fd95ef73 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-jsx.js @@ -0,0 +1,4 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const foo = Global diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-styles-prop.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-styles-prop.js new file mode 100644 index 0000000000..22cfa623c2 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/no-styles-prop.js @@ -0,0 +1,4 @@ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/spread-styles.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/spread-styles.js new file mode 100644 index 0000000000..fd260e830f --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/spread-styles.js @@ -0,0 +1,5 @@ +/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/with-closing-element.js b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/with-closing-element.js new file mode 100644 index 0000000000..dd45e4e190 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__fixtures__/with-closing-element.js @@ -0,0 +1,6 @@ +/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +// prettier-ignore +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/__snapshots__/index.js.snap b/packages/babel-plugin-emotion/__tests__/global-macro/__snapshots__/index.js.snap new file mode 100644 index 0000000000..9e96c7d212 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/__snapshots__/index.js.snap @@ -0,0 +1,206 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`@emotion/core - Global macro basic-array 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => ( + +) + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; +export default (() => );" +`; + +exports[`@emotion/core - Global macro basic-obj 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +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 { Global } from \\"@emotion/core\\"; + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImJhc2ljLW9iai5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHNkIiLCJmaWxlIjoiYmFzaWMtb2JqLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBHbG9iYWwgfSBmcm9tICdAZW1vdGlvbi9jb3JlL21hY3JvJ1xuXG5leHBvcnQgZGVmYXVsdCAoKSA9PiA8R2xvYmFsIHN0eWxlcz17eyBjb2xvcjogJ2hvdHBpbmsnIH19IC8+XG4iXX0= */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + +exports[`@emotion/core - Global macro complex-array 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; + +const getBgColor = () => ({ + backgroundColor: '#fff' +}); + +export default (() => );" +`; + +exports[`@emotion/core - Global macro complex-obj 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const getBgColor = () => ({ backgroundColor: '#fff' }) + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import { css as _css } from \\"@emotion/core\\"; +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; + +const getBgColor = () => ({ + backgroundColor: '#fff' +}); + +export default (() => );" +`; + +exports[`@emotion/core - Global macro css-used-as-value 1`] = ` +"import * as React from 'react' +import { Global, css } from '@emotion/core/macro' + +// this gets ignored by Global macro, but it tests that this combination doesn't crash or something +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 { Global, css } from \\"@emotion/core\\"; // this gets ignored by Global macro, but it tests that this combination doesn't crash or something + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNzcy11c2VkLWFzLXZhbHVlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlxQyIsImZpbGUiOiJjc3MtdXNlZC1hcy12YWx1ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgR2xvYmFsLCBjc3MgfSBmcm9tICdAZW1vdGlvbi9jb3JlL21hY3JvJ1xuXG4vLyB0aGlzIGdldHMgaWdub3JlZCBieSBHbG9iYWwgbWFjcm8sIGJ1dCBpdCB0ZXN0cyB0aGF0IHRoaXMgY29tYmluYXRpb24gZG9lc24ndCBjcmFzaCBvciBzb21ldGhpbmdcbmV4cG9ydCBkZWZhdWx0ICgpID0+IDxHbG9iYWwgc3R5bGVzPXtjc3MoeyBjb2xvcjogJ2hvdHBpbmsnIH0pfSAvPlxuIl19 */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + +exports[`@emotion/core - Global macro no-jsx 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +const foo = Global + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; +const foo = Global;" +`; + +exports[`@emotion/core - Global macro no-styles-prop 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; +export default (() => );" +`; + +exports[`@emotion/core - Global macro spread-styles 1`] = ` +"/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +export default () => + + + ↓ ↓ ↓ ↓ ↓ ↓ + +/* eslint-disable */ +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; +export default (() => );" +`; + +exports[`@emotion/core - Global macro with-closing-element 1`] = ` +"/* eslint-disable */ +import * as React from 'react' +import { Global } from '@emotion/core/macro' + +// prettier-ignore +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).\\"; } + +/* eslint-disable */ +import * as React from 'react'; +import { Global } from \\"@emotion/core\\"; // prettier-ignore + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndpdGgtY2xvc2luZy1lbGVtZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUs2QiIsImZpbGUiOiJ3aXRoLWNsb3NpbmctZWxlbWVudC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlICovXG5pbXBvcnQgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IEdsb2JhbCB9IGZyb20gJ0BlbW90aW9uL2NvcmUvbWFjcm8nXG5cbi8vIHByZXR0aWVyLWlnbm9yZVxuZXhwb3J0IGRlZmF1bHQgKCkgPT4gPEdsb2JhbCBzdHlsZXM9e3sgY29sb3I6ICdob3RwaW5rJyB9fT48L0dsb2JhbD5cbiJdfQ== */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; diff --git a/packages/babel-plugin-emotion/__tests__/global-macro/index.js b/packages/babel-plugin-emotion/__tests__/global-macro/index.js new file mode 100644 index 0000000000..d03d8fcf67 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-macro/index.js @@ -0,0 +1,4 @@ +// @flow +import babelTester from 'babel-tester' + +babelTester('@emotion/core - Global macro', __dirname) diff --git a/packages/babel-plugin-emotion/__tests__/global-requires-options.js b/packages/babel-plugin-emotion/__tests__/global-requires-options.js new file mode 100644 index 0000000000..ac4e71d3b9 --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global-requires-options.js @@ -0,0 +1,17 @@ +// @flow +import babelTester from 'babel-tester' +import plugin from 'babel-plugin-emotion' + +const cases = { + 'source maps can be disabled': { + code: ` +import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => + `, + plugins: [[plugin, { sourceMap: false }]] + } +} + +babelTester('Global inline', cases) diff --git a/packages/babel-plugin-emotion/__tests__/global.js b/packages/babel-plugin-emotion/__tests__/global.js new file mode 100644 index 0000000000..03c0a7b26e --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/global.js @@ -0,0 +1,12 @@ +import babelTester from 'babel-tester' +import plugin from 'babel-plugin-emotion' +import path from 'path' + +babelTester( + 'emotion-babel-plugin Global', + path.join(__dirname, 'global-macro'), + { + plugins: [plugin], + transform: src => src.replace(/\/macro/g, '') + } +) 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/__tests__/source-maps/__fixtures__/global-styles-prop.js b/packages/babel-plugin-emotion/__tests__/source-maps/__fixtures__/global-styles-prop.js new file mode 100644 index 0000000000..3445f909af --- /dev/null +++ b/packages/babel-plugin-emotion/__tests__/source-maps/__fixtures__/global-styles-prop.js @@ -0,0 +1,4 @@ +import * as React from 'react' +import { Global } from '@emotion/core' + +export default () => diff --git a/packages/babel-plugin-emotion/__tests__/source-maps/__snapshots__/index.js.snap b/packages/babel-plugin-emotion/__tests__/source-maps/__snapshots__/index.js.snap index 9400af624d..7240d3245a 100644 --- a/packages/babel-plugin-emotion/__tests__/source-maps/__snapshots__/index.js.snap +++ b/packages/babel-plugin-emotion/__tests__/source-maps/__snapshots__/index.js.snap @@ -127,6 +127,33 @@ var templateObject_1; css(templateObject_1 || (templateObject_1 = __makeTemplateObject(['\\\\n color: hotpink;\\\\n' + (process.env.NODE_ENV === \\"production\\" ? \\"\\" : \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSIsImZpbGUiOiJzb3VyY2UtbWFwLnRlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBfX21ha2VUZW1wbGF0ZU9iamVjdCB9IGZyb20gJ3RzbGliJ1xuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG52YXIgdGVtcGxhdGVPYmplY3RfMVxuXG5jc3MoXG4gIHRlbXBsYXRlT2JqZWN0XzEgfHxcbiAgICAodGVtcGxhdGVPYmplY3RfMSA9IF9fbWFrZVRlbXBsYXRlT2JqZWN0KFxuICAgICAgWydcXG4gIGNvbG9yOiBob3RwaW5rO1xcbiddLFxuICAgICAgWydcXG4gIGNvbG9yOiBob3RwaW5rO1xcbiddXG4gICAgKSlcbilcbiJdfQ== */\\")], ['\\\\n color: hotpink;\\\\n' + (process.env.NODE_ENV === \\"production\\" ? \\"\\" : \\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSIsImZpbGUiOiJzb3VyY2UtbWFwLnRlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBfX21ha2VUZW1wbGF0ZU9iamVjdCB9IGZyb20gJ3RzbGliJ1xuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG52YXIgdGVtcGxhdGVPYmplY3RfMVxuXG5jc3MoXG4gIHRlbXBsYXRlT2JqZWN0XzEgfHxcbiAgICAodGVtcGxhdGVPYmplY3RfMSA9IF9fbWFrZVRlbXBsYXRlT2JqZWN0KFxuICAgICAgWydcXG4gIGNvbG9yOiBob3RwaW5rO1xcbiddLFxuICAgICAgWydcXG4gIGNvbG9yOiBob3RwaW5rO1xcbiddXG4gICAgKSlcbilcbiJdfQ== */\\")])));" `; +exports[`source maps global-styles-prop 1`] = ` +"import * as React from 'react' +import { Global } from '@emotion/core' + +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 { Global } from '@emotion/core'; + +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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS1tYXAudGVzdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHNkIiLCJmaWxlIjoic291cmNlLW1hcC50ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBHbG9iYWwgfSBmcm9tICdAZW1vdGlvbi9jb3JlJ1xuXG5leHBvcnQgZGVmYXVsdCAoKSA9PiA8R2xvYmFsIHN0eWxlcz17eyBjb2xvcjogJ2hvdHBpbmsnIH19IC8+XG4iXX0= */\\", + toString: _EMOTION_STRINGIFIED_CSS_ERROR__ +}; + +export default (() => );" +`; + exports[`source maps styled-object 1`] = ` "import styled from '@emotion/styled' diff --git a/packages/babel-plugin-emotion/src/core-macro.js b/packages/babel-plugin-emotion/src/core-macro.js index f520011eb3..ef17a1060c 100644 --- a/packages/babel-plugin-emotion/src/core-macro.js +++ b/packages/babel-plugin-emotion/src/core-macro.js @@ -1,14 +1,19 @@ // @flow -import { transformExpressionWithStyles, createTransformerMacro } from './utils' +import { + transformExpressionWithStyles, + createTransformerMacro, + getSourceMap, + addImport +} from './utils' export const transformCssCallExpression = ({ - babel, state, + babel, path, sourceMap }: { - babel: *, state: *, + babel: *, path: *, sourceMap?: string }) => { @@ -29,7 +34,50 @@ export const transformCssCallExpression = ({ } } -export let coreCssTransformer = ({ +export const transformInlineCsslessExpression = ({ + state, + babel, + path, + cssImport +}: { + babel: *, + state: *, + path: *, + cssImport: { importSource: string, cssExport: string } +}) => { + let t = babel.types + let expressionPath = path.get('value.expression') + let sourceMap = + state.emotionSourceMap && path.node.loc !== undefined + ? getSourceMap(path.node.loc.start, state) + : '' + + expressionPath.replaceWith( + t.callExpression( + // the name of this identifier doesn't really matter at all + // it'll never appear in generated code + t.identifier('___shouldNeverAppearCSS'), + [path.node.value.expression] + ) + ) + + transformCssCallExpression({ + babel, + state, + path: expressionPath, + sourceMap + }) + + if (t.isCallExpression(expressionPath)) { + expressionPath + .get('callee') + .replaceWith( + addImport(state, cssImport.importSource, cssImport.cssExport, 'css') + ) + } +} + +let cssTransformer = ({ state, babel, reference @@ -41,7 +89,68 @@ export let coreCssTransformer = ({ transformCssCallExpression({ babel, state, path: reference.parentPath }) } -export default createTransformerMacro( - { css: coreCssTransformer }, - { importSource: '@emotion/core' } -) +let globalTransformer = ({ + state, + babel, + reference, + importSource, + options +}: { + state: any, + babel: any, + reference: any, + importSource: string, + options: { cssExport?: string } +}) => { + const t = babel.types + + if ( + !t.isJSXIdentifier(reference.node) || + !t.isJSXOpeningElement(reference.parentPath.node) + ) { + return + } + + const stylesPropPath = reference.parentPath + .get('attributes') + .find(p => t.isJSXAttribute(p.node) && p.node.name.name === 'styles') + + if (!stylesPropPath) { + return + } + + if ( + t.isJSXExpressionContainer(stylesPropPath.node.value) && + (t.isObjectExpression(stylesPropPath.node.value.expression) || + t.isArrayExpression(stylesPropPath.node.value.expression)) + ) { + transformInlineCsslessExpression({ + state, + babel, + path: stylesPropPath, + cssImport: + options.cssExport !== undefined + ? { + importSource, + cssExport: options.cssExport + } + : { + importSource: '@emotion/core', + cssExport: 'css' + } + }) + } +} + +export const transformers = { + // this is an empty function because this transformer is never called + // we don't run any transforms on `jsx` directly + // instead we use it as a hint to enable css prop optimization + jsx: () => {}, + css: cssTransformer, + Global: globalTransformer +} + +export default createTransformerMacro(transformers, { + importSource: '@emotion/core' +}) diff --git a/packages/babel-plugin-emotion/src/index.js b/packages/babel-plugin-emotion/src/index.js index 3ac332ec5d..623253053a 100644 --- a/packages/babel-plugin-emotion/src/index.js +++ b/packages/babel-plugin-emotion/src/index.js @@ -6,15 +6,25 @@ import { } from './emotion-macro' import { createStyledMacro, styledTransformer } from './styled-macro' import coreMacro, { - transformCssCallExpression, - coreCssTransformer + transformers as coreTransformers, + transformInlineCsslessExpression } from './core-macro' -import { - getSourceMap, - getStyledOptions, - addImport, - createTransformerMacro -} from './utils' +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', @@ -35,14 +45,7 @@ let vanillaEmotionMacro = createEmotionMacro('macro') let transformersSource = { emotion: vanillaTransformers, - '@emotion/core': { - // this is an empty function because this transformer is never called - // we don't run any transforms on `jsx` directly - // instead we use it as a hint to enable css prop optimization - jsx: () => {}, - css: coreCssTransformer - // TODO: maybe write transformers for keyframes and Global - }, + '@emotion/core': coreTransformers, '@emotion/styled': { default: [ styledTransformer, @@ -134,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' } ] @@ -149,7 +152,7 @@ export default function(babel: *) { jsxCoreImports.push({ importSource, export: localExportName, - cssExport: null + cssExport: getCssExport('jsx', importSource, value) }) return } @@ -161,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]) @@ -169,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] === coreCssTransformer) { - 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, @@ -239,39 +241,12 @@ export default function(babel: *) { (t.isObjectExpression(path.node.value.expression) || t.isArrayExpression(path.node.value.expression)) ) { - let expressionPath = path.get('value.expression') - let sourceMap = - state.emotionSourceMap && path.node.loc !== undefined - ? getSourceMap(path.node.loc.start, state) - : '' - - expressionPath.replaceWith( - t.callExpression( - // the name of this identifier doesn't really matter at all - // it'll never appear in generated code - t.identifier('___shouldNeverAppearCSS'), - [path.node.value.expression] - ) - ) - - transformCssCallExpression({ - babel, + transformInlineCsslessExpression({ state, - path: expressionPath, - sourceMap + babel, + path, + cssImport: state.jsxCoreImport }) - if (t.isCallExpression(expressionPath)) { - expressionPath - .get('callee') - .replaceWith( - addImport( - state, - state.jsxCoreImport.importSource, - state.jsxCoreImport.cssExport, - 'css' - ) - ) - } } }, CallExpression: {