From 5d86909497e6f824dd33255ee2b50a8019979ff3 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Mon, 28 Jan 2019 16:18:43 +0100 Subject: [PATCH 1/6] Test: Add test which verifies wheter JSX pragma detects WP global --- packages/babel-plugin-import-jsx-pragma/test/index.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/babel-plugin-import-jsx-pragma/test/index.js b/packages/babel-plugin-import-jsx-pragma/test/index.js index 800b75e9727d65..800f6c3c27efc9 100644 --- a/packages/babel-plugin-import-jsx-pragma/test/index.js +++ b/packages/babel-plugin-import-jsx-pragma/test/index.js @@ -52,4 +52,15 @@ describe( 'babel-plugin-import-jsx-pragma', () => { expect( string ).toBe( 'import { createElement } from "@wordpress/element";\nlet foo = ;' ); } ); + + it( 'does nothing if there scope variable already defined when using custom options', () => { + const original = 'const { createElement } = wp.element;\nlet foo = ;'; + const string = getTransformedCode( original, { + scopeVariable: 'createElement', + source: '@wordpress/element', + isDefault: false, + } ); + + expect( string ).toBe( original ); + } ); } ); From 0d2c51a07665695627a2567b4882545d291dfc1d Mon Sep 17 00:00:00 2001 From: Stephen Edgar Date: Tue, 5 Feb 2019 13:39:02 +0100 Subject: [PATCH 2/6] Update packages/babel-plugin-import-jsx-pragma/test/index.js Co-Authored-By: gziolo --- packages/babel-plugin-import-jsx-pragma/test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-plugin-import-jsx-pragma/test/index.js b/packages/babel-plugin-import-jsx-pragma/test/index.js index 800f6c3c27efc9..ca0c65c51b581e 100644 --- a/packages/babel-plugin-import-jsx-pragma/test/index.js +++ b/packages/babel-plugin-import-jsx-pragma/test/index.js @@ -53,7 +53,7 @@ describe( 'babel-plugin-import-jsx-pragma', () => { expect( string ).toBe( 'import { createElement } from "@wordpress/element";\nlet foo = ;' ); } ); - it( 'does nothing if there scope variable already defined when using custom options', () => { + it( 'does nothing if the scope variable is already defined when using custom options', () => { const original = 'const { createElement } = wp.element;\nlet foo = ;'; const string = getTransformedCode( original, { scopeVariable: 'createElement', From 14341ac7897766688735042f54168f60d862b842 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Mon, 11 Feb 2019 12:56:56 +0100 Subject: [PATCH 3/6] Skip import when the scope variable is already defined --- .../src/index.js | 11 ++++++++- .../test/index.js | 24 +++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/babel-plugin-import-jsx-pragma/src/index.js b/packages/babel-plugin-import-jsx-pragma/src/index.js index 89963e67d27e80..f85acb6b9f072a 100644 --- a/packages/babel-plugin-import-jsx-pragma/src/index.js +++ b/packages/babel-plugin-import-jsx-pragma/src/index.js @@ -69,9 +69,18 @@ export default function( babel ) { } } ); }, + VariableDeclaration( path, state ) { + if ( state.hasDeclaredScopeVariable ) { + return; + } + + const { scopeVariable } = getOptions( state ); + + state.hasDeclaredScopeVariable = ! path.scope.parent && path.scope.hasOwnBinding( scopeVariable ); + }, Program: { exit( path, state ) { - if ( ! state.hasJSX || state.hasImportedScopeVariable ) { + if ( ! state.hasJSX || state.hasImportedScopeVariable || state.hasDeclaredScopeVariable ) { return; } diff --git a/packages/babel-plugin-import-jsx-pragma/test/index.js b/packages/babel-plugin-import-jsx-pragma/test/index.js index ca0c65c51b581e..cc84cabbc9bfab 100644 --- a/packages/babel-plugin-import-jsx-pragma/test/index.js +++ b/packages/babel-plugin-import-jsx-pragma/test/index.js @@ -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 = ;'; + const string = getTransformedCode( original ); + + expect( string ).toBe( original ); + } ); + it( 'adds import for scope variable', () => { const original = 'let foo = ;'; const string = getTransformedCode( original ); - expect( string ).toBe( 'import React from "react";\nlet foo = ;' ); + expect( string ).toBe( 'import React from "react";\n' + original ); } ); it( 'allows options customization', () => { @@ -50,17 +57,26 @@ describe( 'babel-plugin-import-jsx-pragma', () => { isDefault: false, } ); - expect( string ).toBe( 'import { createElement } from "@wordpress/element";\nlet foo = ;' ); + expect( string ).toBe( 'import { createElement } from "@wordpress/element";\n' + original ); } ); - it( 'does nothing if the scope variable is already defined when using custom options', () => { - const original = 'const { createElement } = wp.element;\nlet foo = ;'; + it( 'adds import for scope variable even when defined inside the local scope', () => { + const original = 'let foo = ;\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 scope variable is already defined when using custom options', () => { + const original = 'const {\n createElement\n} = wp.element;\nlet foo = ;'; + const string = getTransformedCode( original, { + scopeVariable: 'createElement', + } ); + expect( string ).toBe( original ); } ); } ); From 6961bb9f9432b112a6ff4bde4fc9a1d4e2ed2a3b Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 20 Feb 2019 12:52:55 +0100 Subject: [PATCH 4/6] Add failing tests for inner scope variable defined verification --- packages/babel-plugin-import-jsx-pragma/test/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/babel-plugin-import-jsx-pragma/test/index.js b/packages/babel-plugin-import-jsx-pragma/test/index.js index cc84cabbc9bfab..d70cf2313c540a 100644 --- a/packages/babel-plugin-import-jsx-pragma/test/index.js +++ b/packages/babel-plugin-import-jsx-pragma/test/index.js @@ -71,7 +71,7 @@ describe( 'babel-plugin-import-jsx-pragma', () => { expect( string ).toBe( 'import { createElement } from "@wordpress/element";\n' + original ); } ); - it( 'does nothing if the scope variable is already defined when using custom options', () => { + 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 = ;'; const string = getTransformedCode( original, { scopeVariable: 'createElement', @@ -79,4 +79,13 @@ describe( 'babel-plugin-import-jsx-pragma', () => { 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 = ;\n})();'; + const string = getTransformedCode( original, { + scopeVariable: 'createElement', + } ); + + expect( string ).toBe( original ); + } ); } ); From 2f3986bcfd488b2e21e9ac0fee5a07563d08b7c9 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 20 Feb 2019 14:26:44 +0100 Subject: [PATCH 5/6] Add import statement when there is any undefined scope variable --- .../src/index.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/babel-plugin-import-jsx-pragma/src/index.js b/packages/babel-plugin-import-jsx-pragma/src/index.js index f85acb6b9f072a..68e94e1ffc37d6 100644 --- a/packages/babel-plugin-import-jsx-pragma/src/index.js +++ b/packages/babel-plugin-import-jsx-pragma/src/index.js @@ -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 ) { @@ -69,18 +76,9 @@ export default function( babel ) { } } ); }, - VariableDeclaration( path, state ) { - if ( state.hasDeclaredScopeVariable ) { - return; - } - - const { scopeVariable } = getOptions( state ); - - state.hasDeclaredScopeVariable = ! path.scope.parent && path.scope.hasOwnBinding( scopeVariable ); - }, Program: { exit( path, state ) { - if ( ! state.hasJSX || state.hasImportedScopeVariable || state.hasDeclaredScopeVariable ) { + if ( ! state.hasJSX || state.hasImportedScopeVariable || ! state.hasUndeclaredScopeVariable ) { return; } From f8793f85c44e6c603bfc23987f1b3830bd1a4745 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 20 Feb 2019 14:37:29 +0100 Subject: [PATCH 6/6] Docs: Add details about changes introduced to Babel plugin --- packages/babel-plugin-import-jsx-pragma/CHANGELOG.md | 6 ++++++ packages/babel-plugin-import-jsx-pragma/README.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 33b89b5ae57b01..ffa68f4404f0d4 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -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 diff --git a/packages/babel-plugin-import-jsx-pragma/README.md b/packages/babel-plugin-import-jsx-pragma/README.md index fc32f27a90204e..85d7e69655455a 100644 --- a/packages/babel-plugin-import-jsx-pragma/README.md +++ b/packages/babel-plugin-import-jsx-pragma/README.md @@ -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