-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Framework: Add package: @wordpress/babel-plugin-import-jsx-pragma (#7493
) * Framework: Add package: @wordpress/babel-plugin-import-jsx-pragma * Build: Prebuild babel-plugin-import-jsx-pragma package * Build: Improve import-jsx-pragma docs per review feedback * Build: Consolidate directory testing into filterPackages * Build Tools: Leverage plugin state in place of scope variables
- Loading branch information
Showing
15 changed files
with
358 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package-lock=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
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` (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. | ||
|
||
```js | ||
// .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: | ||
|
||
```js | ||
// .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. | ||
|
||
<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/** | ||
* 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; | ||
|
||
function getOptions( state ) { | ||
if ( ! state._options ) { | ||
state._options = { | ||
...DEFAULT_OPTIONS, | ||
...state.opts, | ||
}; | ||
} | ||
|
||
return state._options; | ||
} | ||
|
||
return { | ||
visitor: { | ||
JSXElement( path, state ) { | ||
state.hasJSX = true; | ||
}, | ||
ImportDeclaration( path, state ) { | ||
if ( state.hasImportedScopeVariable ) { | ||
return; | ||
} | ||
|
||
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. | ||
state.hasImportedScopeVariable = path.node.specifiers.some( ( specifier ) => { | ||
switch ( specifier.type ) { | ||
case 'ImportSpecifier': | ||
return ( | ||
! isDefault && | ||
specifier.imported.name === scopeVariable | ||
); | ||
|
||
case 'ImportDefaultSpecifier': | ||
return isDefault; | ||
} | ||
} ); | ||
}, | ||
Program: { | ||
exit( path, state ) { | ||
if ( ! state.hasJSX || state.hasImportedScopeVariable ) { | ||
return; | ||
} | ||
|
||
const { scopeVariable, source, isDefault } = getOptions( state ); | ||
|
||
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 ); | ||
}, | ||
}, | ||
}, | ||
}; | ||
} |
Oops, something went wrong.