Skip to content

Commit

Permalink
Make Babel import JSX pragma plugin aware of `wp.element.createElemen…
Browse files Browse the repository at this point in the history
…t` (#13809)

* Test: Add test which verifies wheter JSX pragma detects WP global

* Update packages/babel-plugin-import-jsx-pragma/test/index.js

Co-Authored-By: gziolo <grzegorz@gziolo.pl>

* Skip import when the scope variable is already defined

* Add failing tests for inner scope variable defined verification

* Add import statement when there is any undefined scope variable

* Docs: Add details about changes introduced to Babel plugin
  • Loading branch information
gziolo authored and youknowriad committed Mar 6, 2019
1 parent 95fec36 commit 6ddd42e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
6 changes: 6 additions & 0 deletions packages/babel-plugin-import-jsx-pragma/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.0.0 (Unreleased)

### Breaking Change

- Plugin skips now adding import JSX pragma when the scope variable is defined for all JSX elements ([#13809](https://github.com/WordPress/gutenberg/pull/13809)).

## 1.1.0 (2018-09-05)

### New Feature
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-plugin-import-jsx-pragma/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Babel transform plugin for automatically injecting an import to be used as the p

[JSX](https://reactjs.org/docs/jsx-in-depth.html) is merely a syntactic sugar for a function call, typically to `React.createElement` when used with [React](https://reactjs.org/). As such, it requires that the function referenced by this transform be within the scope of the file where the JSX occurs. In a typical React project, this means React must be imported in any file where JSX exists.

**Babel Plugin Import JSX Pragma** automates this process by introducing the necessary import automatically wherever JSX exists, allowing you to use JSX in your code without thinking to ensure the transformed function is within scope.
**Babel Plugin Import JSX Pragma** automates this process by introducing the necessary import automatically wherever JSX exists, allowing you to use JSX in your code without thinking to ensure the transformed function is within scope. It respects existing import statements, as well as scope variable declarations.

## Installation

Expand Down
9 changes: 8 additions & 1 deletion packages/babel-plugin-import-jsx-pragma/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export default function( babel ) {
visitor: {
JSXElement( path, state ) {
state.hasJSX = true;
if ( state.hasUndeclaredScopeVariable ) {
return;
}

const { scopeVariable } = getOptions( state );

state.hasUndeclaredScopeVariable = ! path.scope.hasBinding( scopeVariable );
},
ImportDeclaration( path, state ) {
if ( state.hasImportedScopeVariable ) {
Expand Down Expand Up @@ -71,7 +78,7 @@ export default function( babel ) {
},
Program: {
exit( path, state ) {
if ( ! state.hasJSX || state.hasImportedScopeVariable ) {
if ( ! state.hasJSX || state.hasImportedScopeVariable || ! state.hasUndeclaredScopeVariable ) {
return;
}

Expand Down
40 changes: 38 additions & 2 deletions packages/babel-plugin-import-jsx-pragma/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,18 @@ describe( 'babel-plugin-import-jsx-pragma', () => {
expect( string ).toBe( original );
} );

it( 'does nothing if the scope variable is already defined', () => {
const original = 'const React = require("react");\n\nlet foo = <bar />;';
const string = getTransformedCode( original );

expect( string ).toBe( original );
} );

it( 'adds import for scope variable', () => {
const original = 'let foo = <bar />;';
const string = getTransformedCode( original );

expect( string ).toBe( 'import React from "react";\nlet foo = <bar />;' );
expect( string ).toBe( 'import React from "react";\n' + original );
} );

it( 'allows options customization', () => {
Expand All @@ -50,6 +57,35 @@ describe( 'babel-plugin-import-jsx-pragma', () => {
isDefault: false,
} );

expect( string ).toBe( 'import { createElement } from "@wordpress/element";\nlet foo = <bar />;' );
expect( string ).toBe( 'import { createElement } from "@wordpress/element";\n' + original );
} );

it( 'adds import for scope variable even when defined inside the local scope', () => {
const original = 'let foo = <bar />;\n\nfunction local() {\n const createElement = wp.element.createElement;\n}';
const string = getTransformedCode( original, {
scopeVariable: 'createElement',
source: '@wordpress/element',
isDefault: false,
} );

expect( string ).toBe( 'import { createElement } from "@wordpress/element";\n' + original );
} );

it( 'does nothing if the outer scope variable is already defined when using custom options', () => {
const original = 'const {\n createElement\n} = wp.element;\nlet foo = <bar />;';
const string = getTransformedCode( original, {
scopeVariable: 'createElement',
} );

expect( string ).toBe( original );
} );

it( 'does nothing if the inner scope variable is already defined when using custom options', () => {
const original = '(function () {\n const {\n createElement\n } = wp.element;\n let foo = <bar />;\n})();';
const string = getTransformedCode( original, {
scopeVariable: 'createElement',
} );

expect( string ).toBe( original );
} );
} );

0 comments on commit 6ddd42e

Please sign in to comment.