@astrojs/react
Advanced tools
Comparing version 0.0.0-self-closing-children-20231120173528 to 0.0.0-sessions-20241122114539
import { createElement } from 'react'; | ||
import { render, hydrate, unmountComponentAtNode } from 'react-dom'; | ||
import { hydrate, render, unmountComponentAtNode } from 'react-dom'; | ||
import StaticHtml from './static-html.js'; | ||
@@ -13,3 +13,3 @@ | ||
props, | ||
children != null ? createElement(StaticHtml, { value: children }) : children | ||
children != null ? createElement(StaticHtml, { value: children }) : children, | ||
); | ||
@@ -16,0 +16,0 @@ |
@@ -18,2 +18,6 @@ import { createElement, startTransition } from 'react'; | ||
} | ||
// If the element has no children, we can create a simple React element | ||
if (element.firstChild === null) { | ||
return createElement(element.localName, attrs); | ||
} | ||
@@ -33,3 +37,3 @@ return createElement( | ||
}) | ||
.filter((a) => !!a) | ||
.filter((a) => !!a), | ||
); | ||
@@ -54,7 +58,29 @@ } | ||
// Keep a map of roots so we can reuse them on re-renders | ||
let rootMap = new WeakMap(); | ||
const getOrCreateRoot = (element, creator) => { | ||
let root = rootMap.get(element); | ||
if (!root) { | ||
root = creator(); | ||
rootMap.set(element, root); | ||
} | ||
return root; | ||
}; | ||
export default (element) => | ||
(Component, props, { default: children, ...slotted }, { client }) => { | ||
if (!element.hasAttribute('ssr')) return; | ||
const actionKey = element.getAttribute('data-action-key'); | ||
const actionName = element.getAttribute('data-action-name'); | ||
const stringifiedActionResult = element.getAttribute('data-action-result'); | ||
const formState = | ||
actionKey && actionName && stringifiedActionResult | ||
? [JSON.parse(stringifiedActionResult), actionKey, actionName] | ||
: undefined; | ||
const renderOptions = { | ||
identifierPrefix: element.getAttribute('prefix'), | ||
formState, | ||
}; | ||
@@ -68,3 +94,3 @@ for (const [key, value] of Object.entries(slotted)) { | ||
props, | ||
getChildren(children, element.hasAttribute('data-react-children')) | ||
getChildren(children, element.hasAttribute('data-react-children')), | ||
); | ||
@@ -78,12 +104,18 @@ const rootKey = isAlreadyHydrated(element); | ||
return startTransition(() => { | ||
const root = createRoot(element); | ||
const root = getOrCreateRoot(element, () => { | ||
const r = createRoot(element); | ||
element.addEventListener('astro:unmount', () => r.unmount(), { once: true }); | ||
return r; | ||
}); | ||
root.render(componentEl); | ||
element.addEventListener('astro:unmount', () => root.unmount(), { once: true }); | ||
}); | ||
} | ||
startTransition(() => { | ||
const root = hydrateRoot(element, componentEl, renderOptions); | ||
const root = getOrCreateRoot(element, () => { | ||
const r = hydrateRoot(element, componentEl, renderOptions); | ||
element.addEventListener('astro:unmount', () => r.unmount(), { once: true }); | ||
return r; | ||
}); | ||
root.render(componentEl); | ||
element.addEventListener('astro:unmount', () => root.unmount(), { once: true }); | ||
}); | ||
}; |
import { type Options as ViteReactPluginOptions } from '@vitejs/plugin-react'; | ||
import type { AstroIntegration } from 'astro'; | ||
export type ReactIntegrationOptions = Pick<ViteReactPluginOptions, 'include' | 'exclude'> & { | ||
import type { AstroIntegration, ContainerRenderer } from 'astro'; | ||
export type ReactIntegrationOptions = Pick<ViteReactPluginOptions, 'include' | 'exclude' | 'babel'> & { | ||
experimentalReactChildren?: boolean; | ||
}; | ||
export default function ({ include, exclude, experimentalReactChildren, }?: ReactIntegrationOptions): AstroIntegration; | ||
export default function ({ include, exclude, babel, experimentalReactChildren, }?: ReactIntegrationOptions): AstroIntegration; | ||
export declare function getContainerRenderer(): ContainerRenderer; |
import react, {} from "@vitejs/plugin-react"; | ||
import { version as ReactVersion } from "react-dom"; | ||
import { | ||
getReactMajorVersion, | ||
isUnsupportedVersion, | ||
versionsConfig | ||
} from "./version.js"; | ||
const FAST_REFRESH_PREAMBLE = react.preambleCode; | ||
function getRenderer() { | ||
function getRenderer(reactConfig) { | ||
return { | ||
name: "@astrojs/react", | ||
clientEntrypoint: ReactVersion.startsWith("18.") ? "@astrojs/react/client.js" : "@astrojs/react/client-v17.js", | ||
serverEntrypoint: ReactVersion.startsWith("18.") ? "@astrojs/react/server.js" : "@astrojs/react/server-v17.js" | ||
clientEntrypoint: reactConfig.client, | ||
serverEntrypoint: reactConfig.server | ||
}; | ||
@@ -32,11 +36,7 @@ } | ||
} | ||
function getViteConfiguration({ | ||
include, | ||
exclude, | ||
experimentalReactChildren | ||
} = {}) { | ||
function getViteConfiguration({ include, exclude, babel, experimentalReactChildren } = {}, reactConfig) { | ||
return { | ||
optimizeDeps: { | ||
include: [ | ||
ReactVersion.startsWith("18.") ? "@astrojs/react/client.js" : "@astrojs/react/client-v17.js", | ||
reactConfig.client, | ||
"react", | ||
@@ -47,7 +47,5 @@ "react/jsx-runtime", | ||
], | ||
exclude: [ | ||
ReactVersion.startsWith("18.") ? "@astrojs/react/server.js" : "@astrojs/react/server-v17.js" | ||
] | ||
exclude: [reactConfig.server] | ||
}, | ||
plugins: [react({ include, exclude }), optionsPlugin(!!experimentalReactChildren)], | ||
plugins: [react({ include, exclude, babel }), optionsPlugin(!!experimentalReactChildren)], | ||
resolve: { | ||
@@ -57,3 +55,3 @@ dedupe: ["react", "react-dom", "react-dom/server"] | ||
ssr: { | ||
external: ReactVersion.startsWith("18.") ? ["react-dom/server", "react-dom/client"] : ["react-dom/server.js", "react-dom/client.js"], | ||
external: reactConfig.externals, | ||
noExternal: [ | ||
@@ -64,4 +62,4 @@ // These are all needed to get mui to work. | ||
"@babel/runtime", | ||
"redoc", | ||
"use-immer" | ||
"use-immer", | ||
"@material-tailwind/react" | ||
] | ||
@@ -74,4 +72,10 @@ } | ||
exclude, | ||
babel, | ||
experimentalReactChildren | ||
} = {}) { | ||
const majorVersion = getReactMajorVersion(); | ||
if (isUnsupportedVersion(majorVersion)) { | ||
throw new Error(`Unsupported React version: ${majorVersion}.`); | ||
} | ||
const versionConfig = versionsConfig[majorVersion]; | ||
return { | ||
@@ -81,5 +85,8 @@ name: "@astrojs/react", | ||
"astro:config:setup": ({ command, addRenderer, updateConfig, injectScript }) => { | ||
addRenderer(getRenderer()); | ||
addRenderer(getRenderer(versionConfig)); | ||
updateConfig({ | ||
vite: getViteConfiguration({ include, exclude, experimentalReactChildren }) | ||
vite: getViteConfiguration( | ||
{ include, exclude, babel, experimentalReactChildren }, | ||
versionConfig | ||
) | ||
}); | ||
@@ -94,4 +101,16 @@ if (command === "dev") { | ||
} | ||
function getContainerRenderer() { | ||
const majorVersion = getReactMajorVersion(); | ||
if (isUnsupportedVersion(majorVersion)) { | ||
throw new Error(`Unsupported React version: ${majorVersion}.`); | ||
} | ||
const versionConfig = versionsConfig[majorVersion]; | ||
return { | ||
name: "@astrojs/react", | ||
serverEntrypoint: versionConfig.server | ||
}; | ||
} | ||
export { | ||
src_default as default | ||
src_default as default, | ||
getContainerRenderer | ||
}; |
{ | ||
"name": "@astrojs/react", | ||
"description": "Use React components within Astro", | ||
"version": "0.0.0-self-closing-children-20231120173528", | ||
"version": "0.0.0-sessions-20241122114539", | ||
"type": "module", | ||
@@ -11,3 +11,3 @@ "types": "./dist/index.d.ts", | ||
"type": "git", | ||
"url": "https://github.com/withastro/astro.git", | ||
"url": "git+https://github.com/withastro/astro.git", | ||
"directory": "packages/integrations/react" | ||
@@ -25,2 +25,3 @@ }, | ||
".": "./dist/index.js", | ||
"./actions": "./dist/actions.js", | ||
"./client.js": "./client.js", | ||
@@ -40,3 +41,5 @@ "./client-v17.js": "./client-v17.js", | ||
"server.js", | ||
"server.d.ts", | ||
"server-v17.js", | ||
"server-v17.d.ts", | ||
"static-html.js", | ||
@@ -46,15 +49,13 @@ "vnode-children.js" | ||
"dependencies": { | ||
"@vitejs/plugin-react": "^4.0.4", | ||
"ultrahtml": "^1.3.0" | ||
"@vitejs/plugin-react": "^4.3.3", | ||
"ultrahtml": "^1.5.3", | ||
"vite": "6.0.0-beta.6" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.2.21", | ||
"@types/react-dom": "^18.2.7", | ||
"chai": "^4.3.7", | ||
"cheerio": "1.0.0-rc.12", | ||
"react": "^18.1.0", | ||
"react-dom": "^18.1.0", | ||
"vite": "^4.4.9", | ||
"mocha": "^10.2.0", | ||
"astro": "0.0.0-self-closing-children-20231120173528", | ||
"@types/react": "^18.3.12", | ||
"@types/react-dom": "^18.3.1", | ||
"cheerio": "1.0.0", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"astro": "0.0.0-sessions-20241122114539", | ||
"astro-scripts": "0.0.14" | ||
@@ -65,7 +66,7 @@ }, | ||
"@types/react-dom": "^17.0.17 || ^18.0.6", | ||
"react": "^17.0.2 || ^18.0.0", | ||
"react-dom": "^17.0.2 || ^18.0.0" | ||
"react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta", | ||
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta" | ||
}, | ||
"engines": { | ||
"node": ">=18.14.1" | ||
"node": "^18.17.1 || ^20.3.0 || >=21.0.0" | ||
}, | ||
@@ -79,4 +80,4 @@ "publishConfig": { | ||
"dev": "astro-scripts dev \"src/**/*.ts\"", | ||
"test": "mocha --exit --timeout 20000" | ||
"test": "astro-scripts test \"test/**/*.test.js\"" | ||
} | ||
} |
154
README.md
@@ -5,147 +5,35 @@ # @astrojs/react ⚛️ | ||
## Installation | ||
## Documentation | ||
There are two ways to add integrations to your project. Let's try the most convenient option first! | ||
Read the [`@astrojs/react` docs][docs] | ||
### `astro add` command | ||
## Support | ||
Astro includes a CLI tool for adding first party integrations: `astro add`. This command will: | ||
- Get help in the [Astro Discord][discord]. Post questions in our `#support` forum, or visit our dedicated `#dev` channel to discuss current development and more! | ||
1. (Optionally) Install all necessary dependencies and peer dependencies | ||
2. (Also optionally) Update your `astro.config.*` file to apply this integration | ||
- Check our [Astro Integration Documentation][astro-integration] for more on integrations. | ||
To install `@astrojs/react`, run the following from your project directory and follow the prompts: | ||
- Submit bug reports and feature requests as [GitHub issues][issues]. | ||
```sh | ||
# Using NPM | ||
npx astro add react | ||
# Using Yarn | ||
yarn astro add react | ||
# Using PNPM | ||
pnpm astro add react | ||
``` | ||
## Contributing | ||
If you run into any issues, [feel free to report them to us on GitHub](https://github.com/withastro/astro/issues) and try the manual installation steps below. | ||
This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! These links will help you get started: | ||
### Install dependencies manually | ||
- [Contributor Manual][contributing] | ||
- [Code of Conduct][coc] | ||
- [Community Guide][community] | ||
First, install the `@astrojs/react` integration like so: | ||
## License | ||
```sh | ||
npm install @astrojs/react | ||
``` | ||
MIT | ||
Most package managers will install associated peer dependencies as well. Still, if you see a "Cannot find package 'react'" (or similar) warning when you start up Astro, you'll need to install `react` and `react-dom`: | ||
Copyright (c) 2023–present [Astro][astro] | ||
```sh | ||
npm install react react-dom | ||
``` | ||
Now, apply this integration to your `astro.config.*` file using the `integrations` property: | ||
```diff lang="js" "react()" | ||
// astro.config.mjs | ||
import { defineConfig } from 'astro/config'; | ||
+ import react from '@astrojs/react'; | ||
export default defineConfig({ | ||
// ... | ||
integrations: [react()], | ||
// ^^^^^^^ | ||
}); | ||
``` | ||
## Getting started | ||
To use your first React component in Astro, head to our [UI framework documentation][astro-ui-frameworks]. You'll explore: | ||
- 📦 how framework components are loaded, | ||
- 💧 client-side hydration options, and | ||
- 🤝 opportunities to mix and nest frameworks together | ||
## Options | ||
### Combining multiple JSX frameworks | ||
When you are using multiple JSX frameworks (React, Preact, Solid) in the same project, Astro needs to determine which JSX framework-specific transformations should be used for each of your components. If you have only added one JSX framework integration to your project, no extra configuration is needed. | ||
Use the `include` (required) and `exclude` (optional) configuration options to specify which files belong to which framework. Provide an array of files and/or folders to `include` for each framework you are using. Wildcards may be used to include multiple file paths. | ||
We recommend placing common framework components in the same folder (e.g. `/components/react/` and `/components/solid/`) to make specifying your includes easier, but this is not required: | ||
```js | ||
// astro.config.mjs | ||
import { defineConfig } from 'astro/config'; | ||
import preact from '@astrojs/preact'; | ||
import react from '@astrojs/react'; | ||
import svelte from '@astrojs/svelte'; | ||
import vue from '@astrojs/vue'; | ||
import solid from '@astrojs/solid-js'; | ||
export default defineConfig({ | ||
// Enable many frameworks to support all different kinds of components. | ||
// No `include` is needed if you are only using a single JSX framework! | ||
integrations: [ | ||
preact({ | ||
include: ['**/preact/*'], | ||
}), | ||
react({ | ||
include: ['**/react/*'], | ||
}), | ||
solid({ | ||
include: ['**/solid/*'], | ||
}), | ||
], | ||
}); | ||
``` | ||
### Children parsing | ||
Children passed into a React component from an Astro component are parsed as plain strings, not React nodes. | ||
For example, the `<ReactComponent />` below will only receive a single child element: | ||
```astro | ||
--- | ||
import ReactComponent from './ReactComponent'; | ||
--- | ||
<ReactComponent> | ||
<div>one</div> | ||
<div>two</div> | ||
</ReactComponent> | ||
``` | ||
If you are using a library that _expects_ more than one child element to be passed, for example so that it can slot certain elements in different places, you might find this to be a blocker. | ||
You can set the experimental flag `experimentalReactChildren` to tell Astro to always pass children to React as React vnodes. There is some runtime cost to this, but it can help with compatibility. | ||
You can enable this option in the configuration for the React integration: | ||
```js | ||
// astro.config.mjs | ||
import { defineConfig } from 'astro/config'; | ||
import react from '@astrojs/react'; | ||
export default defineConfig({ | ||
// ... | ||
integrations: [ | ||
react({ | ||
experimentalReactChildren: true, | ||
}), | ||
], | ||
}); | ||
``` | ||
## Troubleshooting | ||
For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help! | ||
You can also check our [Astro Integration Documentation][astro-integration] for more on integrations. | ||
## Contributing | ||
This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! | ||
[astro]: https://astro.build/ | ||
[docs]: https://docs.astro.build/en/guides/integrations-guide/react/ | ||
[contributing]: https://github.com/withastro/astro/blob/main/CONTRIBUTING.md | ||
[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md | ||
[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md | ||
[discord]: https://astro.build/chat/ | ||
[issues]: https://github.com/withastro/astro/issues | ||
[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ | ||
[astro-ui-frameworks]: https://docs.astro.build/en/core-concepts/framework-components/#using-framework-components |
@@ -8,10 +8,2 @@ import React from 'react'; | ||
function errorIsComingFromPreactComponent(err) { | ||
return ( | ||
err.message && | ||
(err.message.startsWith("Cannot read property '__H'") || | ||
err.message.includes("(reading '__H')")) | ||
); | ||
} | ||
function check(Component, props, children) { | ||
@@ -24,2 +16,3 @@ // Note: there are packages that do some unholy things to create "components". | ||
if (typeof Component !== 'function') return false; | ||
if (Component.name === 'QwikComponent') return false; | ||
@@ -30,3 +23,2 @@ if (Component.prototype != null && typeof Component.prototype.render === 'function') { | ||
let error = null; | ||
let isReactComponent = false; | ||
@@ -39,7 +31,3 @@ function Tester(...args) { | ||
} | ||
} catch (err) { | ||
if (!errorIsComingFromPreactComponent(err)) { | ||
error = err; | ||
} | ||
} | ||
} catch {} | ||
@@ -51,5 +39,2 @@ return React.createElement('div'); | ||
if (error) { | ||
throw error; | ||
} | ||
return isReactComponent; | ||
@@ -89,2 +74,3 @@ } | ||
export default { | ||
name: '@astrojs/react', | ||
check, | ||
@@ -91,0 +77,0 @@ renderToStaticMarkup, |
115
server.js
@@ -0,6 +1,6 @@ | ||
import opts from 'astro:react:opts'; | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/server'; | ||
import { incrementId } from './context.js'; | ||
import StaticHtml from './static-html.js'; | ||
import { incrementId } from './context.js'; | ||
import opts from 'astro:react:opts'; | ||
@@ -10,10 +10,2 @@ const slotName = (str) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase()); | ||
function errorIsComingFromPreactComponent(err) { | ||
return ( | ||
err.message && | ||
(err.message.startsWith("Cannot read property '__H'") || | ||
err.message.includes("(reading '__H')")) | ||
); | ||
} | ||
async function check(Component, props, children) { | ||
@@ -26,3 +18,8 @@ // Note: there are packages that do some unholy things to create "components". | ||
if (typeof Component !== 'function') return false; | ||
if (Component.name === 'QwikComponent') return false; | ||
// Preact forwarded-ref components can be functions, which React does not support | ||
if (typeof Component === 'function' && Component['$$typeof'] === Symbol.for('react.forward_ref')) | ||
return false; | ||
if (Component.prototype != null && typeof Component.prototype.render === 'function') { | ||
@@ -32,3 +29,2 @@ return React.Component.isPrototypeOf(Component) || React.PureComponent.isPrototypeOf(Component); | ||
let error = null; | ||
let isReactComponent = false; | ||
@@ -41,7 +37,3 @@ function Tester(...args) { | ||
} | ||
} catch (err) { | ||
if (!errorIsComingFromPreactComponent(err)) { | ||
error = err; | ||
} | ||
} | ||
} catch {} | ||
@@ -53,5 +45,2 @@ return React.createElement('div'); | ||
if (error) { | ||
throw error; | ||
} | ||
return isReactComponent; | ||
@@ -104,19 +93,18 @@ } | ||
} | ||
const formState = this ? await getFormState(this) : undefined; | ||
if (formState) { | ||
attrs['data-action-result'] = JSON.stringify(formState[0]); | ||
attrs['data-action-key'] = formState[1]; | ||
attrs['data-action-name'] = formState[2]; | ||
} | ||
const vnode = React.createElement(Component, newProps); | ||
const renderOptions = { | ||
identifierPrefix: prefix, | ||
formState, | ||
}; | ||
let html; | ||
if (metadata?.hydrate) { | ||
if ('renderToReadableStream' in ReactDOM) { | ||
html = await renderToReadableStreamAsync(vnode, renderOptions); | ||
} else { | ||
html = await renderToPipeableStreamAsync(vnode, renderOptions); | ||
} | ||
if ('renderToReadableStream' in ReactDOM) { | ||
html = await renderToReadableStreamAsync(vnode, renderOptions); | ||
} else { | ||
if ('renderToReadableStream' in ReactDOM) { | ||
html = await renderToReadableStreamAsync(vnode, renderOptions); | ||
} else { | ||
html = await renderToStaticNodeStreamAsync(vnode, renderOptions); | ||
} | ||
html = await renderToPipeableStreamAsync(vnode, renderOptions); | ||
} | ||
@@ -126,2 +114,34 @@ return { html, attrs }; | ||
/** | ||
* @returns {Promise<[actionResult: any, actionKey: string, actionName: string] | undefined>} | ||
*/ | ||
async function getFormState({ result }) { | ||
const { request, actionResult } = result; | ||
if (!actionResult) return undefined; | ||
if (!isFormRequest(request.headers.get('content-type'))) return undefined; | ||
const { searchParams } = new URL(request.url); | ||
const formData = await request.clone().formData(); | ||
/** | ||
* The key generated by React to identify each `useActionState()` call. | ||
* @example "k511f74df5a35d32e7cf266450d85cb6c" | ||
*/ | ||
const actionKey = formData.get('$ACTION_KEY')?.toString(); | ||
/** | ||
* The action name returned by an action's `toString()` property. | ||
* This matches the endpoint path. | ||
* @example "/_actions/blog.like" | ||
*/ | ||
const actionName = | ||
searchParams.get('_astroAction') ?? | ||
/* Legacy. TODO: remove for stable */ formData | ||
.get('_astroAction') | ||
?.toString(); | ||
if (!actionKey || !actionName) return undefined; | ||
return [actionResult, actionKey, actionName]; | ||
} | ||
async function renderToPipeableStreamAsync(vnode, options) { | ||
@@ -148,3 +168,3 @@ const Writable = await getNodeWritable(); | ||
}, | ||
}) | ||
}), | ||
); | ||
@@ -156,24 +176,2 @@ }, | ||
async function renderToStaticNodeStreamAsync(vnode, options) { | ||
const Writable = await getNodeWritable(); | ||
let html = ''; | ||
return new Promise((resolve, reject) => { | ||
let stream = ReactDOM.renderToStaticNodeStream(vnode, options); | ||
stream.on('error', (err) => { | ||
reject(err); | ||
}); | ||
stream.pipe( | ||
new Writable({ | ||
write(chunk, _encoding, callback) { | ||
html += chunk.toString('utf-8'); | ||
callback(); | ||
}, | ||
destroy() { | ||
resolve(html); | ||
}, | ||
}) | ||
); | ||
}); | ||
} | ||
/** | ||
@@ -207,3 +205,14 @@ * Use a while loop instead of "for await" due to cloudflare and Vercel Edge issues | ||
const formContentTypes = ['application/x-www-form-urlencoded', 'multipart/form-data']; | ||
function isFormRequest(contentType) { | ||
// Split off parameters like charset or boundary | ||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type#content-type_in_html_forms | ||
const type = contentType?.split(';')[0].toLowerCase(); | ||
return formContentTypes.some((t) => type === t); | ||
} | ||
export default { | ||
name: '@astrojs/react', | ||
check, | ||
@@ -210,0 +219,0 @@ renderToStaticMarkup, |
@@ -1,3 +0,3 @@ | ||
import { parse, DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'; | ||
import { createElement, Fragment } from 'react'; | ||
import { Fragment, createElement } from 'react'; | ||
import { DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE, parse } from 'ultrahtml'; | ||
@@ -11,7 +11,6 @@ let ids = 0; | ||
function createReactElementFromNode(node) { | ||
const childVnodes = Array.isArray(node.children) && node.children.length | ||
? node.children | ||
.map((child) => createReactElementFromNode(child)) | ||
.filter(Boolean) | ||
: undefined; | ||
const childVnodes = | ||
Array.isArray(node.children) && node.children.length | ||
? node.children.map((child) => createReactElementFromNode(child)).filter(Boolean) | ||
: undefined; | ||
@@ -18,0 +17,0 @@ if (node.type === DOCUMENT_NODE) { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30524
7
18
709
7
39
+ Addedvite@6.0.0-beta.6
+ Addedreact@19.0.0(transitive)
+ Addedreact-dom@19.0.0(transitive)
+ Addedscheduler@0.25.0(transitive)
+ Addedvite@6.0.0-beta.6(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedreact@18.3.1(transitive)
- Removedreact-dom@18.3.1(transitive)
- Removedscheduler@0.23.2(transitive)
Updated@vitejs/plugin-react@^4.3.3
Updatedultrahtml@^1.5.3