Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

import-jsx

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

import-jsx - npm Package Compare versions

Comparing version 4.0.1 to 5.0.0

89

cache.js

@@ -1,44 +0,33 @@

'use strict';
// Based on https://github.com/babel/babel-loader/blob/15df92fafd58ec53ba88efa22de7b2cee5e65fcc/src/cache.js
const fs = require('fs');
const os = require('os');
const path = require('path');
const crypto = require('crypto');
const makeDir = require('make-dir');
const findCacheDir = require('find-cache-dir');
const transform = require('./transform');
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import crypto from 'node:crypto';
import makeDir from 'make-dir';
import findCacheDir from 'find-cache-dir';
import packageConfig from './package.json' assert {type: 'json'};
let directory;
const cacheDirectory = findCacheDir({name: 'import-jsx'}) || os.tmpdir();
/**
* Build the filename for the cached file
*
* @param {String} source Original contents of the file to be cached
* @param {Object} options Options passed to importJsx
* @param {String} version Version of import-jsx
*
* @return {String}
*/
const filename = (source, options, version) => {
const hash = crypto.createHash('md5');
const contents = JSON.stringify({source, options, version});
hash.update(contents);
export const cacheKeyFromSource = source => {
const contents = JSON.stringify({
source,
version: packageConfig.version
});
return hash.digest('hex') + '.js';
return crypto.createHash('md5').update(contents).digest('hex') + '.js';
};
/**
* Handle the cache
*
* @params {String} directory
* @params {Object} parameters
*/
const handleCache = (directory, parameters) => {
const {modulePath, options, source, version} = parameters;
const cachedTransform = async (
transform,
parameters,
directory = cacheDirectory
) => {
const {enabled, key} = parameters;
if (!options.cache) {
return transform(source, options, modulePath);
if (!enabled) {
return transform();
}
const file = path.join(directory, filename(source, options, version));
const file = path.join(directory, key);

@@ -48,5 +37,4 @@ try {

// we just need to return it
return fs.readFileSync(file).toString();
// eslint-disable-next-line no-unused-vars
} catch (error) {}
return await fs.readFile(file, 'utf8');
} catch {}

@@ -57,6 +45,6 @@ const fallback = directory !== os.tmpdir();

try {
makeDir.sync(directory);
await makeDir(directory);
} catch (error) {
if (fallback) {
return handleCache(os.tmpdir(), parameters);
return cachedTransform(transform, parameters, os.tmpdir());
}

@@ -69,10 +57,10 @@

// return it to the user asap and write it in cache
const result = transform(source, options, modulePath);
const result = await transform();
try {
fs.writeFileSync(file, result);
await fs.writeFile(file, result);
} catch (error) {
if (fallback) {
// Fallback to tmpdir if node_modules folder not writable
return handleCache(os.tmpdir(), parameters);
return cachedTransform(transform, parameters, os.tmpdir());
}

@@ -86,17 +74,2 @@

/**
* Retrieve file from cache, or create a new one for future reads
*
* @param {Object} parameters
* @param {String} parameters.modulePath
* @param {String} parameters.source Original contents of the file to be cached
* @param {Object} parameters.options Options passed to importJsx
* @param {String} parameters.version Version of import-jsx
*/
module.exports = parameters => {
if (!directory) {
directory = findCacheDir({name: 'import-jsx'}) || os.tmpdir();
}
return handleCache(directory, parameters);
};
export default cachedTransform;

@@ -1,67 +0,43 @@

'use strict';
const path = require('path');
const resolveFrom = require('resolve-from');
const callerPath = require('caller-path');
const cache = require('./cache');
const {version} = require('./package.json');
import process from 'node:process';
import cachedTransform, {cacheKeyFromSource} from './cache.js';
import transform from './transform.js';
const importJsx = (moduleId, options) => {
if (typeof moduleId !== 'string') {
throw new TypeError('Expected a string');
export const load = async (url, _context, nextLoad) => {
if (!url.endsWith('.js') || url.includes('node_modules')) {
return nextLoad(url);
}
options = {
pragma: 'h',
pragmaFrag: 'Fragment',
cache: true,
...options
};
const result = await nextLoad(url);
const modulePath = resolveFrom(path.dirname(callerPath()), moduleId);
if (!options.cache) {
delete require.cache[modulePath];
if (!result.source) {
return result;
}
// If they used .jsx, and there's already a .jsx, then hook there
// Otherwise, hook node's default .js
const ext = path.extname(modulePath);
const hookExt = require.extensions[ext] ? ext : '.js';
const source = result.source.toString();
const oldExtension = require.extensions[hookExt];
const useCache =
process.env.IMPORT_JSX_CACHE !== '0' &&
process.env.IMPORT_JSX_CACHE !== 'false';
require.extensions[hookExt] = module => {
const oldCompile = module._compile;
const cacheKey = cacheKeyFromSource(source);
module._compile = source => {
const result = cache({
modulePath,
options,
source,
version
});
try {
const transformedSource = await cachedTransform(
() => {
return transform(source, url);
},
{
enabled: useCache,
key: cacheKey
}
);
module._compile = oldCompile;
module._compile(result, modulePath);
return {
source: transformedSource,
format: 'module',
shortCircuit: true
};
require.extensions[hookExt] = oldExtension;
oldExtension(module, modulePath);
};
const m = require(modulePath);
require.extensions[hookExt] = oldExtension;
if (!options.cache) {
delete require.cache[modulePath];
} catch {
return nextLoad(url);
}
return m;
};
module.exports = importJsx;
module.exports.default = importJsx;
module.exports.create = options => {
return moduleId => importJsx(moduleId, options);
};
{
"name": "import-jsx",
"version": "4.0.1",
"version": "5.0.0",
"description": "Require and transpile JSX on the fly",

@@ -12,7 +12,9 @@ "license": "MIT",

},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=10"
"node": ">=14.16"
},
"scripts": {
"test": "xo && ava"
"test": "xo && ava --serial"
},

@@ -32,16 +34,18 @@ "files": [

"dependencies": {
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
"@babel/plugin-transform-destructuring": "^7.5.0",
"@babel/plugin-transform-react-jsx": "^7.3.0",
"caller-path": "^3.0.1",
"find-cache-dir": "^3.2.0",
"make-dir": "^3.0.2",
"resolve-from": "^3.0.0",
"rimraf": "^3.0.0"
"@babel/core": "^7.21.0",
"@babel/preset-react": "^7.18.6",
"find-cache-dir": "^4.0.0",
"make-dir": "^3.1.0"
},
"devDependencies": {
"ava": "^0.19.1",
"@babel/eslint-parser": "^7.19.1",
"ava": "^5.2.0",
"del": "^7.0.0",
"execa": "^7.0.0",
"preact": "^10.13.0",
"preact-render-to-string": "^5.2.6",
"prettier": "^2.0.2",
"xo": "^0.28.1"
"react": "^18.2.0",
"react-dom": "^18.2.0",
"xo": "^0.53.1"
},

@@ -56,9 +60,18 @@ "prettier": {

"xo": {
"prettier": true,
"parser": "@babel/eslint-parser",
"parserOptions": {
"requireConfigFile": false,
"babelOptions": {
"parserOpts": {
"plugins": [
"importAssertions"
]
}
}
},
"ignore": [
"test/fixtures"
],
"rules": {
"node/no-deprecated-api": "off"
}
]
}
}
# import-jsx ![Build Status](https://github.com/vadimdemedes/import-jsx/workflows/test/badge.svg)
> Require and transpile JSX on the fly
> Import and transpile JSX via [loader hooks](https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#loaders). It doesn't transpile anything besides JSX and caches transpiled sources by default.
- Doesn't install any `require()` hooks
- Auto-detects React pragma (`React.createElement`) and falls back to `h` pragma supported by Preact and others
- Caches transpiled sources by default
- Bundles in [object rest spread](https://babeljs.io/docs/plugins/transform-object-rest-spread/) transform
## Install
```console
npm install import-jsx
```
$ npm install --save import-jsx
```
## Usage
```js
const importJsx = require('import-jsx');
> **Note**:
> `import-jsx` only works with ES modules.
const reactComponent = importJsx('./react');
const preactComponent = importJsx('./preact');
const customComponent = importJsx('./custom', {pragma: 'x'});
```sh
node --loader=import-jsx react-example.js
```
**React**
**react-example.js**
```jsx
const React = require('react');
module.exports = <div />;
const HelloWorld = () => <h1>Hello world</h1>;
```
**Preact**
## Examples
```jsx
const {h} = require('preact');
### React
module.exports = <div />;
```
React is auto-detected by default and `react` will be auto-imported, if it's not already.
**Any JSX pragma**
```jsx
const x = (tagName, attrs, ...children) => {};
module.exports = <div />;
const HelloWorld = () => <h1>Hello world</h1>;
```
## API
### Preact
### importJsx(moduleId, [options])
If an alternative library is used and exports `createElement`, like Preact, configure `import-jsx` to import it instead of React:
#### moduleId
```jsx
/** @jsxImportSource preact */
Type: `string`
const HelloWorld = () => <h1>Hello world</h1>;
```
Module id.
### Any JSX pragma
#### options
For libraries not compatible with React's API, but which still support JSX, import it and configure `import-jsx` to use its pragma:
##### pragma
```jsx
/** @jsxRuntime classic */
/** @jsx h */
import h from 'vhtml';
Type: `string`<br>
Default: `h`
const HelloWorld = () => <h1>Hello world</h1>;
```
Override [JSX pragma](https://jasonformat.com/wtf-is-jsx/).
### CLI
##### pragmaFrag
`import-jsx` can be used to transpile JSX inside CLI entrypoints defined in `bin` section of `package.json` and their imported files.
Type: `string`<br>
Default: `Fragment`
For example, given this **package.json**:
Override pragma for [JSX fragments](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#pragmafrag).
```json
{
"name": "my-amazing-cli",
"bin": "cli.js"
}
```
##### cache
Insert this hashbang at the beginning of **cli.js**:
Type: `boolean`<br>
Default: `true`
```jsx
#!/usr/bin/env NODE_NO_WARNINGS=1 node --loader=import-jsx
Cache transpiled source code.
const HelloWorld = () => <h1>Hello world</h1>;
```
### importJsx.create([options])
### Disable cache
Factory method to create a version of `importJsx()` with pre-defined options.
Useful when you need a custom pragma, but don't want to pass it along with each `importJsx()` call.
`import-jsx` caches transpiled sources by default, so that the same file is transpiled only once.
If that's not a desired behavior, turn off caching by setting `IMPORT_JSX_CACHE=0` or `IMPORT_JSX_CACHE=false` environment variable.
#### options
Type: `object`
Options to pass to `importJsx()`.
```js
// Before
const importJsx = require('import-jsx');
importJsx('./a', {pragma: 'x'});
importJsx('./b', {pragma: 'x'});
// After
const importJsx = require('import-jsx').create({pragma: 'x'});
importJsx('./a');
importJsx('./b');
```console
IMPORT_JSX_CACHE=0 node --loader=import-jsx my-code.js
```

@@ -1,31 +0,26 @@

'use strict';
// Only load these if compiled source is not already cached
let babel;
let jsxTransform;
let reactPreset;
const transform = (source, options, modulePath) => {
const transform = async (source, filename) => {
if (!babel) {
babel = require('@babel/core');
jsxTransform = require('@babel/plugin-transform-react-jsx');
babel = await import('@babel/core');
reactPreset = await import('@babel/preset-react');
}
if (source.includes('React')) {
options.pragma = 'React.createElement';
options.pragmaFrag = 'React.Fragment';
}
const plugins = [
const presets = [
[
jsxTransform,
reactPreset.default,
{
pragma: options.pragma,
pragmaFrag: options.pragmaFrag,
useBuiltIns: true
runtime: 'automatic',
pure: false,
useBuiltIns: true,
useSpread: true
}
]
].filter(Boolean);
];
const result = babel.transformSync(source, {
plugins,
filename: modulePath,
const result = await babel.transformAsync(source, {
presets,
filename,
sourceMaps: 'inline',

@@ -39,2 +34,2 @@ babelrc: false,

module.exports = transform;
export default transform;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc