From c846b72d6503916648b669c2fc2704ea124f56c4 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 22 Jun 2018 14:42:29 -0400 Subject: [PATCH 1/5] Framework: Add package: @wordpress/babel-plugin-import-jsx-pragma --- bin/packages/get-babel-config.js | 21 ++-- eslint/config.js | 16 +-- package.json | 16 +++ .../babel-plugin-import-jsx-pragma/.npmrc | 1 + .../babel-plugin-import-jsx-pragma/README.md | 90 ++++++++++++++ .../package.json | 31 +++++ .../src/index.js | 112 ++++++++++++++++++ .../test/index.js | 54 +++++++++ packages/data/src/index.js | 1 - packages/data/src/test/index.js | 2 +- packages/element/README.md | 4 +- packages/element/src/test/serialize.js | 1 - .../src/components/plugin-area/index.js | 2 +- .../src/components/plugin-context/index.js | 2 +- 14 files changed, 325 insertions(+), 28 deletions(-) create mode 100644 packages/babel-plugin-import-jsx-pragma/.npmrc create mode 100644 packages/babel-plugin-import-jsx-pragma/README.md create mode 100644 packages/babel-plugin-import-jsx-pragma/package.json create mode 100644 packages/babel-plugin-import-jsx-pragma/src/index.js create mode 100644 packages/babel-plugin-import-jsx-pragma/test/index.js diff --git a/bin/packages/get-babel-config.js b/bin/packages/get-babel-config.js index 99fac50c9effd..afea64fc4326c 100644 --- a/bin/packages/get-babel-config.js +++ b/bin/packages/get-babel-config.js @@ -10,14 +10,21 @@ const babelPresetEnv = require( 'babel-preset-env' ); */ const babelDefaultConfig = require( '@wordpress/babel-preset-default' ); -const plugins = map( babelDefaultConfig.plugins, ( plugin ) => { - if ( isArray( plugin ) && plugin[ 0 ] === babelPluginTransformReactJSX ) { - // TODO: It should become the default value when all modules are moved to packages. - return [ babelPluginTransformReactJSX, { pragma: 'createElement' } ]; - } +const plugins = [ + ...map( babelDefaultConfig.plugins, ( plugin ) => { + if ( isArray( plugin ) && plugin[ 0 ] === babelPluginTransformReactJSX ) { + // TODO: It should become the default value when all modules are moved to packages. + return [ babelPluginTransformReactJSX, { pragma: 'createElement' } ]; + } - return plugin; -} ); + return plugin; + } ), + [ require( '../../packages/babel-plugin-import-jsx-pragma' ).default, { + scopeVariable: 'createElement', + source: '@wordpress/element', + isDefault: false, + } ], +]; const babelConfigs = { main: Object.assign( diff --git a/eslint/config.js b/eslint/config.js index 16c60464eb639..9e15ac3a2761e 100644 --- a/eslint/config.js +++ b/eslint/config.js @@ -27,11 +27,6 @@ module.exports = { 'react', 'jsx-a11y', ], - settings: { - react: { - pragma: 'wp', - }, - }, rules: { 'array-bracket-spacing': [ 'error', 'always' ], 'arrow-parens': [ 'error', 'always' ], @@ -117,6 +112,7 @@ module.exports = { 'react/jsx-tag-spacing': 'error', 'react/no-children-prop': 'off', 'react/prop-types': 'off', + 'react/react-in-jsx-scope': 'off', semi: 'error', 'semi-spacing': 'error', 'space-before-blocks': [ 'error', 'always' ], @@ -160,14 +156,4 @@ module.exports = { 'valid-typeof': 'error', yoda: 'off', }, - overrides: [ - { - files: 'packages/**/*.js', - settings: { - react: { - pragma: 'createElement', - }, - }, - }, - ], }; diff --git a/package.json b/package.json index 358ba58d6c8fc..2eda2b03c7171 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,22 @@ "presets": [ "@wordpress/default" ], + "plugins": [ + [ + "./packages/babel-plugin-import-jsx-pragma", + { + "scopeVariable": "createElement", + "source": "@wordpress/element", + "isDefault": false + } + ], + [ + "babel-plugin-transform-react-jsx", + { + "pragma": "createElement" + } + ] + ], "env": { "production": { "plugins": [ diff --git a/packages/babel-plugin-import-jsx-pragma/.npmrc b/packages/babel-plugin-import-jsx-pragma/.npmrc new file mode 100644 index 0000000000000..43c97e719a5a8 --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/babel-plugin-import-jsx-pragma/README.md b/packages/babel-plugin-import-jsx-pragma/README.md new file mode 100644 index 0000000000000..1f69c74114292 --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/README.md @@ -0,0 +1,90 @@ +Babel Plugin Import JSX Pragma +====== + +Babel transform plugin for automatically injecting an import to be used as the +pragma for the [React JSX Transform plugin](http://babeljs.io/docs/en/babel-plugin-transform-react-jsx). + +[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. + +## Installation + +Install the module to your project using [npm](https://www.npmjs.com/). + +```bash +npm install @wordpress/babel-plugin-import-jsx-pragma +``` + +## Usage + +Refer to the [Babel Plugins documentation](http://babeljs.io/docs/en/plugins) +if you don't yet have experience working with Babel plugins. + +Include `@wordpress/babel-plugin-import-jsx-pragma` as a plugin in your Babel +configuration. + +It's assumed that you're also using [@babel/transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/). +Otherwise, you may encounter errors when encountering JSX tokens. + +``` +// .babelrc.js +module.exports = { + plugins: [ + '@wordpress/babel-plugin-import-jsx-pragma', + '@babel/transform-react-jsx', + ], +}; +``` + +## Options + +As the `@babel/transform-react-jsx` plugin offers options to customize the +`pragma` to which the transform references, there are equivalent options to +assign for customizing the imports generated. + +For example, if you are using the `@wordpress/element` package, you may want to +use the following configuration: + +``` +// .babelrc.js +module.exports = { + plugins: [ + [ '@wordpress/babel-plugin-import-jsx-pragma', { + scopeVariable: 'createElement', + source: '@wordpress/element', + isDefault: false, + } ], + [ '@babel/transform-react-jsx', { + pragma: 'createElement', + } ], + ], +}; +``` + +### `scopeVariable` + +_Type:_ String + +Name of variable required to be in scope for use by the JSX pragma. For the +default pragma of React.createElement, the React variable must be within scope. + +### `source` + +_Type:_ String + +The module from which the scope variable is to be imported when missing. + +### `isDefautl` + +_Type:_ Boolean + +Whether the scopeVariable is the default import of the source module. + +

Code is Poetry.

diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json new file mode 100644 index 0000000000000..e699619bc939f --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -0,0 +1,31 @@ +{ + "name": "@wordpress/babel-plugin-import-jsx-pragma", + "version": "1.0.0-alpha.1", + "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "babel-plugin", + "jsx", + "pragma", + "react" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/babel-plugin-import-jsx-pragma/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "devDependencies": { + "babel-core": "^6.26.3", + "babel-plugin-syntax-jsx": "^6.18.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/babel-plugin-import-jsx-pragma/src/index.js b/packages/babel-plugin-import-jsx-pragma/src/index.js new file mode 100644 index 0000000000000..b9f36459568a9 --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/src/index.js @@ -0,0 +1,112 @@ +/** + * Default options for the plugin. + * + * @property {string} scopeVariable Name of variable required to be in scope + * for use by the JSX pragma. For the default + * pragma of React.createElement, the React + * variable must be within scope. + * @property {string} source The module from which the scope variable + * is to be imported when missing. + * @property {boolean} isDefault Whether the scopeVariable is the default + * import of the source module. + */ +const DEFAULT_OPTIONS = { + scopeVariable: 'React', + source: 'react', + isDefault: true, +}; + +/** + * Babel transform plugin for automatically injecting an import to be used as + * the pragma for the React JSX Transform plugin. + * + * @see http://babeljs.io/docs/en/babel-plugin-transform-react-jsx + * + * @param {Object} babel Babel instance. + * + * @return {Object} Babel transform plugin. + */ +export default function( babel ) { + const { types: t } = babel; + + let _options; + + let hasJSX, hasImportedScopeVariable; + + function getOptions( options ) { + if ( ! _options ) { + _options = { + ...DEFAULT_OPTIONS, + ...options, + }; + } + + return _options; + } + + return { + visitor: { + JSXElement() { + hasJSX = true; + }, + ImportDeclaration( path, state ) { + if ( hasImportedScopeVariable ) { + return; + } + + const { scopeVariable, isDefault } = getOptions( state.opts ); + + // The module source isn't verified, since if at least the + // required variable is within scope, its assumed to be + // compatible with the targeted transform, and otherwise would + // conflict as a duplicate import if introduced separately. + + hasImportedScopeVariable = path.node.specifiers.some( ( specifier ) => { + switch ( specifier.type ) { + case 'ImportSpecifier': + return ( + ! isDefault && + specifier.imported.name === scopeVariable + ); + + case 'ImportDefaultSpecifier': + return isDefault; + } + } ); + }, + Program: { + enter() { + _options = null; + hasJSX = false; + hasImportedScopeVariable = false; + }, + exit( path, state ) { + if ( ! hasJSX || hasImportedScopeVariable ) { + return; + } + + const { scopeVariable, source, isDefault } = getOptions( state.opts ); + + let specifier; + if ( isDefault ) { + specifier = t.importDefaultSpecifier( + t.identifier( scopeVariable ) + ); + } else { + specifier = t.importSpecifier( + t.identifier( scopeVariable ), + t.identifier( scopeVariable ) + ); + } + + const importDeclaration = t.importDeclaration( + [ specifier ], + t.stringLiteral( source ) + ); + + path.unshiftContainer( 'body', importDeclaration ); + }, + }, + }, + }; +} diff --git a/packages/babel-plugin-import-jsx-pragma/test/index.js b/packages/babel-plugin-import-jsx-pragma/test/index.js new file mode 100644 index 0000000000000..166df12462a13 --- /dev/null +++ b/packages/babel-plugin-import-jsx-pragma/test/index.js @@ -0,0 +1,54 @@ +/** + * External dependencies + */ +import { transform } from 'babel-core'; + +/** + * Internal dependencies + */ +import plugin from '../src'; + +describe( 'babel-plugin-import-jsx-pragma', () => { + function getTransformedCode( source, options = {} ) { + const { code } = transform( source, { + plugins: [ + [ plugin, options ], + 'syntax-jsx', + ], + } ); + + return code; + } + + it( 'does nothing if there is no jsx', () => { + const original = 'let foo;'; + const string = getTransformedCode( original ); + + expect( string ).toBe( original ); + } ); + + it( 'does nothing if there scope variable already imported', () => { + const original = 'import React from "react";let 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 = ;' ); + } ); + + it( 'allows options customization', () => { + const original = 'let foo = ;'; + const string = getTransformedCode( original, { + scopeVariable: 'createElement', + source: '@wordpress/element', + isDefault: false, + } ); + + expect( string ).toBe( 'import { createElement } from "@wordpress/element";\nlet foo = ;' ); + } ); +} ); diff --git a/packages/data/src/index.js b/packages/data/src/index.js index 14247b8bb601c..23cb9d6f81545 100644 --- a/packages/data/src/index.js +++ b/packages/data/src/index.js @@ -10,7 +10,6 @@ import { flowRight, without, mapValues, overEvery } from 'lodash'; import { Component, compose, - createElement, createHigherOrderComponent, pure, } from '@wordpress/element'; diff --git a/packages/data/src/test/index.js b/packages/data/src/test/index.js index 816b3914dc5e5..25dab32ba8fc3 100644 --- a/packages/data/src/test/index.js +++ b/packages/data/src/test/index.js @@ -7,7 +7,7 @@ import { castArray } from 'lodash'; /** * WordPress dependencies */ -import { compose, createElement } from '@wordpress/element'; +import { compose } from '@wordpress/element'; /** * Internal dependencies diff --git a/packages/element/README.md b/packages/element/README.md index 9d0076183e144..23ea3cef7b652 100644 --- a/packages/element/README.md +++ b/packages/element/README.md @@ -64,10 +64,12 @@ If you've configured [Babel](http://babeljs.io/) for your project, you can opt i { "plugins": [ [ "transform-react-jsx", { - "pragma": "wp.element.createElement" + "pragma": "createElement" } ] ] } ``` +This assumes that you will import the `createElement` function in any file where you use JSX. Alternatively, consider using the [`@wordpress/babel-plugin-import-jsx-pragma` Babel plugin](https://www.npmjs.com/package/@wordpress/babel-plugin-import-jsx-pragma) to automate the import of this function. +

Code is Poetry.

diff --git a/packages/element/src/test/serialize.js b/packages/element/src/test/serialize.js index 2408c75e7b27f..7307e944ab2a1 100644 --- a/packages/element/src/test/serialize.js +++ b/packages/element/src/test/serialize.js @@ -8,7 +8,6 @@ import { noop } from 'lodash'; */ import { Component, - createElement, Fragment, RawHTML, } from '../'; diff --git a/packages/plugins/src/components/plugin-area/index.js b/packages/plugins/src/components/plugin-area/index.js index 1beeccc5317de..4bfd74176991f 100644 --- a/packages/plugins/src/components/plugin-area/index.js +++ b/packages/plugins/src/components/plugin-area/index.js @@ -6,7 +6,7 @@ import { map } from 'lodash'; /** * WordPress dependencies */ -import { Component, createElement } from '@wordpress/element'; +import { Component } from '@wordpress/element'; import { addAction, removeAction } from '@wordpress/hooks'; /** diff --git a/packages/plugins/src/components/plugin-context/index.js b/packages/plugins/src/components/plugin-context/index.js index f640dd0b66f18..3bf3030780bc7 100644 --- a/packages/plugins/src/components/plugin-context/index.js +++ b/packages/plugins/src/components/plugin-context/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { createContext, createHigherOrderComponent, createElement } from '@wordpress/element'; +import { createContext, createHigherOrderComponent } from '@wordpress/element'; const { Consumer, Provider } = createContext( { name: null, From 09feb723251c8e40c51b0842c046b4de60b0029a Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Tue, 26 Jun 2018 12:05:05 -0400 Subject: [PATCH 2/5] Build: Prebuild babel-plugin-import-jsx-pragma package --- bin/packages/get-babel-config.js | 23 ++++++++------- bin/packages/get-packages.js | 49 +++++++++++++++++++++++++++++++- package.json | 4 ++- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/bin/packages/get-babel-config.js b/bin/packages/get-babel-config.js index afea64fc4326c..9008b8c61e3bb 100644 --- a/bin/packages/get-babel-config.js +++ b/bin/packages/get-babel-config.js @@ -10,21 +10,22 @@ const babelPresetEnv = require( 'babel-preset-env' ); */ const babelDefaultConfig = require( '@wordpress/babel-preset-default' ); -const plugins = [ - ...map( babelDefaultConfig.plugins, ( plugin ) => { - if ( isArray( plugin ) && plugin[ 0 ] === babelPluginTransformReactJSX ) { - // TODO: It should become the default value when all modules are moved to packages. - return [ babelPluginTransformReactJSX, { pragma: 'createElement' } ]; - } +const plugins = map( babelDefaultConfig.plugins, ( plugin ) => { + if ( isArray( plugin ) && plugin[ 0 ] === babelPluginTransformReactJSX ) { + // TODO: It should become the default value when all modules are moved to packages. + return [ babelPluginTransformReactJSX, { pragma: 'createElement' } ]; + } + + return plugin; +} ); - return plugin; - } ), - [ require( '../../packages/babel-plugin-import-jsx-pragma' ).default, { +if ( process.env.TRANSFORM_JSX_PRAGMA ) { + plugins.push( [ require( '../../packages/babel-plugin-import-jsx-pragma' ).default, { scopeVariable: 'createElement', source: '@wordpress/element', isDefault: false, - } ], -]; + } ] ); +} const babelConfigs = { main: Object.assign( diff --git a/bin/packages/get-packages.js b/bin/packages/get-packages.js index 1aec2d3f858e3..9a3d02c6e85cd 100644 --- a/bin/packages/get-packages.js +++ b/bin/packages/get-packages.js @@ -3,12 +3,58 @@ */ const fs = require( 'fs' ); const path = require( 'path' ); +const { overEvery, compact, includes, negate } = require( 'lodash' ); /** - * Module Constants + * Absolute path to packages directory. + * + * @type {string} */ const PACKAGES_DIR = path.resolve( __dirname, '../../packages' ); +const { + /** + * Comma-separated string of packages to include in build. + * + * @type {string} + */ + INCLUDE_PACKAGES, + + /** + * Comma-separated string of packages to exclude from build. + * + * @type {string} + */ + EXCLUDE_PACKAGES, +} = process.env; + +/** + * Given a comma-separated string, returns a filter function which returns true + * if the item is contained within as a comma-separated entry. + * + * @param {Function} filterFn Filter function to call with item to test. + * @param {string} list Comma-separated list of items. + * + * @return {Function} Filter function. + */ +const createCommaSeparatedFilter = ( filterFn, list ) => { + const listItems = list.split( ',' ); + return ( item ) => filterFn( listItems, item ); +}; + +/** + * Filter predicate, returning true if the given base file name is to be + * included in the build, based on BUILD_PACKAGES environment variable. + * + * @param {string} pkg File base name to test. + * + * @return {boolean} Whether to include file in build. + */ +const filterPackages = overEvery( compact( [ + INCLUDE_PACKAGES && createCommaSeparatedFilter( includes, INCLUDE_PACKAGES ), + EXCLUDE_PACKAGES && createCommaSeparatedFilter( negate( includes ), EXCLUDE_PACKAGES ), +] ) ); + /** * Returns the absolute path of all WordPress packages * @@ -17,6 +63,7 @@ const PACKAGES_DIR = path.resolve( __dirname, '../../packages' ); function getPackages() { return fs .readdirSync( PACKAGES_DIR ) + .filter( filterPackages ) .map( ( file ) => path.resolve( PACKAGES_DIR, file ) ) .filter( ( f ) => fs.lstatSync( path.resolve( f ) ).isDirectory() ); } diff --git a/package.json b/package.json index 2eda2b03c7171..d136d7e3287f9 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,9 @@ }, "scripts": { "prebuild": "npm run check-engines", - "build:packages": "rimraf ./packages/*/build ./packages/*/build-module && node ./bin/packages/build.js", + "clean:packages": "rimraf ./packages/*/build ./packages/*/build-module", + "prebuild:packages": "npm run clean:packages && INCLUDE_PACKAGES=babel-plugin-import-jsx-pragma node ./bin/packages/build.js", + "build:packages": "TRANSFORM_JSX_PRAGMA=1 EXCLUDE_PACKAGES=babel-plugin-import-jsx-pragma node ./bin/packages/build.js", "build": "npm run build:packages && cross-env NODE_ENV=production webpack", "check-engines": "check-node-version --package", "ci": "concurrently \"npm run lint && npm run build\" \"npm run test-unit:coverage-ci\"", From aad1bedd82617b6c667ad82f86f35b1592082860 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Tue, 26 Jun 2018 12:10:51 -0400 Subject: [PATCH 3/5] Build: Improve import-jsx-pragma docs per review feedback --- .../babel-plugin-import-jsx-pragma/README.md | 36 ++++++------------- .../src/index.js | 9 +++-- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/packages/babel-plugin-import-jsx-pragma/README.md b/packages/babel-plugin-import-jsx-pragma/README.md index 1f69c74114292..c4f5e309281bd 100644 --- a/packages/babel-plugin-import-jsx-pragma/README.md +++ b/packages/babel-plugin-import-jsx-pragma/README.md @@ -1,18 +1,11 @@ Babel Plugin Import JSX Pragma ====== -Babel transform plugin for automatically injecting an import to be used as the -pragma for the [React JSX Transform plugin](http://babeljs.io/docs/en/babel-plugin-transform-react-jsx). +Babel transform plugin for automatically injecting an import to be used as the pragma for the [React JSX Transform plugin](http://babeljs.io/docs/en/babel-plugin-transform-react-jsx). -[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. +[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. ## Installation @@ -24,16 +17,11 @@ npm install @wordpress/babel-plugin-import-jsx-pragma ## Usage -Refer to the [Babel Plugins documentation](http://babeljs.io/docs/en/plugins) -if you don't yet have experience working with Babel plugins. +Refer to the [Babel Plugins documentation](http://babeljs.io/docs/en/plugins) if you don't yet have experience working with Babel plugins. -Include `@wordpress/babel-plugin-import-jsx-pragma` as a plugin in your Babel -configuration. +Include `@wordpress/babel-plugin-import-jsx-pragma` (and [@babel/transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/)) as plugins in your Babel configuration. If you don't include both you will receive errors when encountering JSX tokens. -It's assumed that you're also using [@babel/transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/). -Otherwise, you may encounter errors when encountering JSX tokens. - -``` +```js // .babelrc.js module.exports = { plugins: [ @@ -45,14 +33,11 @@ module.exports = { ## Options -As the `@babel/transform-react-jsx` plugin offers options to customize the -`pragma` to which the transform references, there are equivalent options to -assign for customizing the imports generated. +As the `@babel/transform-react-jsx` plugin offers options to customize the `pragma` to which the transform references, there are equivalent options to assign for customizing the imports generated. -For example, if you are using the `@wordpress/element` package, you may want to -use the following configuration: +For example, if you are using the `@wordpress/element` package, you may want to use the following configuration: -``` +```js // .babelrc.js module.exports = { plugins: [ @@ -72,8 +57,7 @@ module.exports = { _Type:_ String -Name of variable required to be in scope for use by the JSX pragma. For the -default pragma of React.createElement, the React variable must be within scope. +Name of variable required to be in scope for use by the JSX pragma. For the default pragma of React.createElement, the React variable must be within scope. ### `source` diff --git a/packages/babel-plugin-import-jsx-pragma/src/index.js b/packages/babel-plugin-import-jsx-pragma/src/index.js index b9f36459568a9..5deb4e4cb0f81 100644 --- a/packages/babel-plugin-import-jsx-pragma/src/index.js +++ b/packages/babel-plugin-import-jsx-pragma/src/index.js @@ -56,11 +56,10 @@ export default function( babel ) { const { scopeVariable, isDefault } = getOptions( state.opts ); - // The module source isn't verified, since if at least the - // required variable is within scope, its assumed to be - // compatible with the targeted transform, and otherwise would - // conflict as a duplicate import if introduced separately. - + // Test that at least one import specifier exists matching the + // scope variable name. The module source is not verfied since + // we must avoid introducing a conflicting import name, even if + // the scope variable is referenced from a different source. hasImportedScopeVariable = path.node.specifiers.some( ( specifier ) => { switch ( specifier.type ) { case 'ImportSpecifier': From 980d38bd56f7f44567c2ea709737010c5e88170f Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Tue, 26 Jun 2018 12:15:24 -0400 Subject: [PATCH 4/5] Build: Consolidate directory testing into filterPackages --- bin/packages/get-packages.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/bin/packages/get-packages.js b/bin/packages/get-packages.js index 9a3d02c6e85cd..30093a22abba6 100644 --- a/bin/packages/get-packages.js +++ b/bin/packages/get-packages.js @@ -42,15 +42,28 @@ const createCommaSeparatedFilter = ( filterFn, list ) => { return ( item ) => filterFn( listItems, item ); }; +/** + * Returns true if the given base file name for a file within the packages + * directory is itself a directory. + * + * @param {string} file Packages directory file. + * + * @return {boolean} Whether file is a directory. + */ +function isDirectory( file ) { + return fs.lstatSync( path.resolve( PACKAGES_DIR, file ) ).isDirectory(); +} + /** * Filter predicate, returning true if the given base file name is to be - * included in the build, based on BUILD_PACKAGES environment variable. + * included in the build. * * @param {string} pkg File base name to test. * * @return {boolean} Whether to include file in build. */ const filterPackages = overEvery( compact( [ + isDirectory, INCLUDE_PACKAGES && createCommaSeparatedFilter( includes, INCLUDE_PACKAGES ), EXCLUDE_PACKAGES && createCommaSeparatedFilter( negate( includes ), EXCLUDE_PACKAGES ), ] ) ); @@ -64,8 +77,7 @@ function getPackages() { return fs .readdirSync( PACKAGES_DIR ) .filter( filterPackages ) - .map( ( file ) => path.resolve( PACKAGES_DIR, file ) ) - .filter( ( f ) => fs.lstatSync( path.resolve( f ) ).isDirectory() ); + .map( ( file ) => path.resolve( PACKAGES_DIR, file ) ); } module.exports = getPackages; From 67653d04c85153374da1d0b585a502a14a834eee Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 27 Jun 2018 09:50:35 -0400 Subject: [PATCH 5/5] Build Tools: Leverage plugin state in place of scope variables --- .../src/index.js | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/babel-plugin-import-jsx-pragma/src/index.js b/packages/babel-plugin-import-jsx-pragma/src/index.js index 5deb4e4cb0f81..9ce777d32e186 100644 --- a/packages/babel-plugin-import-jsx-pragma/src/index.js +++ b/packages/babel-plugin-import-jsx-pragma/src/index.js @@ -29,38 +29,34 @@ const DEFAULT_OPTIONS = { export default function( babel ) { const { types: t } = babel; - let _options; - - let hasJSX, hasImportedScopeVariable; - - function getOptions( options ) { - if ( ! _options ) { - _options = { + function getOptions( state ) { + if ( ! state._options ) { + state._options = { ...DEFAULT_OPTIONS, - ...options, + ...state.opts, }; } - return _options; + return state._options; } return { visitor: { - JSXElement() { - hasJSX = true; + JSXElement( path, state ) { + state.hasJSX = true; }, ImportDeclaration( path, state ) { - if ( hasImportedScopeVariable ) { + if ( state.hasImportedScopeVariable ) { return; } - const { scopeVariable, isDefault } = getOptions( state.opts ); + const { scopeVariable, isDefault } = getOptions( state ); // Test that at least one import specifier exists matching the // scope variable name. The module source is not verfied since // we must avoid introducing a conflicting import name, even if // the scope variable is referenced from a different source. - hasImportedScopeVariable = path.node.specifiers.some( ( specifier ) => { + state.hasImportedScopeVariable = path.node.specifiers.some( ( specifier ) => { switch ( specifier.type ) { case 'ImportSpecifier': return ( @@ -74,17 +70,12 @@ export default function( babel ) { } ); }, Program: { - enter() { - _options = null; - hasJSX = false; - hasImportedScopeVariable = false; - }, exit( path, state ) { - if ( ! hasJSX || hasImportedScopeVariable ) { + if ( ! state.hasJSX || state.hasImportedScopeVariable ) { return; } - const { scopeVariable, source, isDefault } = getOptions( state.opts ); + const { scopeVariable, source, isDefault } = getOptions( state ); let specifier; if ( isDefault ) {