summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/yellow-snakes-jam.md21
-rw-r--r--packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx5
-rw-r--r--packages/integrations/react/README.md40
-rw-r--r--packages/integrations/react/package.json8
-rw-r--r--packages/integrations/react/server.js6
-rw-r--r--packages/integrations/react/src/index.ts36
-rw-r--r--packages/integrations/react/test/fixtures/react-component/astro.config.mjs (renamed from packages/astro/test/fixtures/react-component/astro.config.mjs)6
-rw-r--r--packages/integrations/react/test/fixtures/react-component/package.json (renamed from packages/astro/test/fixtures/react-component/package.json)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/ArrowFunction.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/ArrowFunction.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/CloneElement.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/CloneElement.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/ForgotImport.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/ForgotImport.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/GetSearch.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/GetSearch.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/Goodbye.vue (renamed from packages/astro/test/fixtures/react-component/src/components/Goodbye.vue)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/Hello.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/Hello.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/LazyComponent.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/LazyComponent.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/PragmaComment.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx (renamed from packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/PropsSpread.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/PropsSpread.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/Pure.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/Pure.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/Research.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/Research.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/Suspense.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/Suspense.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/ThrowsAnError.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/ThrowsAnError.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/TypeScriptComponent.tsx (renamed from packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/WithChildren.jsx10
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/components/WithId.jsx (renamed from packages/astro/test/fixtures/react-component/src/components/WithId.jsx)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/pages/children.astro14
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/pages/error-rendering.astro (renamed from packages/astro/test/fixtures/react-component/src/pages/error-rendering.astro)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/pages/index.astro (renamed from packages/astro/test/fixtures/react-component/src/pages/index.astro)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/pages/pragma-comment.astro (renamed from packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/pages/suspense.astro (renamed from packages/astro/test/fixtures/react-component/src/pages/suspense.astro)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/skipped-pages/forgot-import.astro (renamed from packages/astro/test/fixtures/react-component/src/skipped-pages/forgot-import.astro)0
-rw-r--r--packages/integrations/react/test/fixtures/react-component/src/skipped-pages/window.astro (renamed from packages/astro/test/fixtures/react-component/src/skipped-pages/window.astro)0
-rw-r--r--packages/integrations/react/test/react-component.test.js (renamed from packages/astro/test/react-component.test.js)14
-rw-r--r--packages/integrations/react/vnode-children.js38
-rw-r--r--pnpm-lock.yaml58
36 files changed, 218 insertions, 38 deletions
diff --git a/.changeset/yellow-snakes-jam.md b/.changeset/yellow-snakes-jam.md
new file mode 100644
index 000000000..87c4d1da7
--- /dev/null
+++ b/.changeset/yellow-snakes-jam.md
@@ -0,0 +1,21 @@
+---
+'@astrojs/react': minor
+---
+
+Optionally parse React slots as React children.
+
+This adds a new configuration option for the React integration `experimentalReactChildren`:
+
+```js
+export default {
+ integrations: [
+ react({
+ experimentalReactChildren: true,
+ })
+ ]
+}
+```
+
+With this enabled, children passed to React from Astro components via the default slot are parsed as React components.
+
+This enables better compatibility with certain React components which manipulate their children.
diff --git a/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx b/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx
deleted file mode 100644
index cdcb0e0a6..000000000
--- a/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react';
-
-export default function ({ children }) {
- return <div className="with-children">{children}</div>;
-}
diff --git a/packages/integrations/react/README.md b/packages/integrations/react/README.md
index 48c45881f..7504490e0 100644
--- a/packages/integrations/react/README.md
+++ b/packages/integrations/react/README.md
@@ -61,6 +61,46 @@ To use your first React component in Astro, head to our [UI framework documentat
- 💧 client-side hydration options, and
- 🤝 opportunities to mix and nest frameworks together
+## Options
+
+### 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 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!
diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json
index 31527a9e4..e238e21b9 100644
--- a/packages/integrations/react/package.json
+++ b/packages/integrations/react/package.json
@@ -45,7 +45,8 @@
},
"dependencies": {
"@babel/core": "^7.22.5",
- "@babel/plugin-transform-react-jsx": "^7.22.5"
+ "@babel/plugin-transform-react-jsx": "^7.22.5",
+ "ultrahtml": "^1.2.0"
},
"devDependencies": {
"@types/react": "^17.0.62",
@@ -53,7 +54,10 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"react": "^18.1.0",
- "react-dom": "^18.1.0"
+ "react-dom": "^18.1.0",
+ "chai": "^4.3.7",
+ "cheerio": "1.0.0-rc.12",
+ "vite": "^4.4.6"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js
index 8c02c4b26..3f0d93e97 100644
--- a/packages/integrations/react/server.js
+++ b/packages/integrations/react/server.js
@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom/server';
import StaticHtml from './static-html.js';
import { incrementId } from './context.js';
+import opts from 'astro:react:opts';
const slotName = (str) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
const reactTypeof = Symbol.for('react.element');
@@ -85,7 +86,10 @@ async function renderToStaticMarkup(Component, props, { default: children, ...sl
...slots,
};
const newChildren = children ?? props.children;
- if (newChildren != null) {
+ if (children && opts.experimentalReactChildren) {
+ const convert = await import('./vnode-children.js').then(mod => mod.default);
+ newProps.children = convert(children);
+ } else if (newChildren != null) {
newProps.children = React.createElement(StaticHtml, {
hydrate: needsHydration(metadata),
value: newChildren,
diff --git a/packages/integrations/react/src/index.ts b/packages/integrations/react/src/index.ts
index d7906fe4a..556062282 100644
--- a/packages/integrations/react/src/index.ts
+++ b/packages/integrations/react/src/index.ts
@@ -1,5 +1,6 @@
import type { AstroIntegration } from 'astro';
import { version as ReactVersion } from 'react-dom';
+import type * as vite from 'vite';
function getRenderer() {
return {
@@ -36,7 +37,29 @@ function getRenderer() {
};
}
-function getViteConfiguration() {
+function optionsPlugin(experimentalReactChildren: boolean): vite.Plugin {
+ const virtualModule = 'astro:react:opts';
+ const virtualModuleId = '\0' + virtualModule;
+ return {
+ name: '@astrojs/react:opts',
+ resolveId(id) {
+ if(id === virtualModule) {
+ return virtualModuleId;
+ }
+ },
+ load(id) {
+ if(id === virtualModuleId) {
+ return {
+ code: `export default {
+ experimentalReactChildren: ${JSON.stringify(experimentalReactChildren)}
+ }`
+ };
+ }
+ }
+ };
+}
+
+function getViteConfiguration(experimentalReactChildren: boolean) {
return {
optimizeDeps: {
include: [
@@ -70,16 +93,23 @@ function getViteConfiguration() {
'use-immer',
],
},
+ plugins: [
+ optionsPlugin(experimentalReactChildren)
+ ]
};
}
-export default function (): AstroIntegration {
+export type ReactIntegrationOptions = {
+ experimentalReactChildren: boolean;
+}
+
+export default function ({ experimentalReactChildren }: ReactIntegrationOptions = { experimentalReactChildren: false }): AstroIntegration {
return {
name: '@astrojs/react',
hooks: {
'astro:config:setup': ({ addRenderer, updateConfig }) => {
addRenderer(getRenderer());
- updateConfig({ vite: getViteConfiguration() });
+ updateConfig({ vite: getViteConfiguration(experimentalReactChildren) });
},
},
};
diff --git a/packages/astro/test/fixtures/react-component/astro.config.mjs b/packages/integrations/react/test/fixtures/react-component/astro.config.mjs
index 53d0bd03b..cd54d60f8 100644
--- a/packages/astro/test/fixtures/react-component/astro.config.mjs
+++ b/packages/integrations/react/test/fixtures/react-component/astro.config.mjs
@@ -4,5 +4,7 @@ import vue from '@astrojs/vue';
// https://astro.build/config
export default defineConfig({
- integrations: [react(), vue()],
-}); \ No newline at end of file
+ integrations: [react({
+ experimentalReactChildren: true,
+ }), vue()],
+});
diff --git a/packages/astro/test/fixtures/react-component/package.json b/packages/integrations/react/test/fixtures/react-component/package.json
index cf7b2b057..cf7b2b057 100644
--- a/packages/astro/test/fixtures/react-component/package.json
+++ b/packages/integrations/react/test/fixtures/react-component/package.json
diff --git a/packages/astro/test/fixtures/react-component/src/components/ArrowFunction.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/ArrowFunction.jsx
index 16fac5bb6..16fac5bb6 100644
--- a/packages/astro/test/fixtures/react-component/src/components/ArrowFunction.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/ArrowFunction.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/CloneElement.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/CloneElement.jsx
index 809ac4aa4..809ac4aa4 100644
--- a/packages/astro/test/fixtures/react-component/src/components/CloneElement.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/CloneElement.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/ForgotImport.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/ForgotImport.jsx
index 9ee27faca..9ee27faca 100644
--- a/packages/astro/test/fixtures/react-component/src/components/ForgotImport.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/ForgotImport.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/GetSearch.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/GetSearch.jsx
index d3fee2f9a..d3fee2f9a 100644
--- a/packages/astro/test/fixtures/react-component/src/components/GetSearch.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/GetSearch.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/Goodbye.vue b/packages/integrations/react/test/fixtures/react-component/src/components/Goodbye.vue
index 430dfdb71..430dfdb71 100644
--- a/packages/astro/test/fixtures/react-component/src/components/Goodbye.vue
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/Goodbye.vue
diff --git a/packages/astro/test/fixtures/react-component/src/components/Hello.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/Hello.jsx
index 4c241162d..4c241162d 100644
--- a/packages/astro/test/fixtures/react-component/src/components/Hello.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/Hello.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx
index d6ff21dc3..d6ff21dc3 100644
--- a/packages/astro/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/ImportsThrowsAnError.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/LazyComponent.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/LazyComponent.jsx
index b43aa36be..b43aa36be 100644
--- a/packages/astro/test/fixtures/react-component/src/components/LazyComponent.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/LazyComponent.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/PragmaComment.jsx
index d8ea77810..d8ea77810 100644
--- a/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/PragmaComment.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx b/packages/integrations/react/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx
index 9f2256fbf..9f2256fbf 100644
--- a/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/PropsSpread.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/PropsSpread.jsx
index 044c2a019..044c2a019 100644
--- a/packages/astro/test/fixtures/react-component/src/components/PropsSpread.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/PropsSpread.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/Pure.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/Pure.jsx
index 6fae8613b..6fae8613b 100644
--- a/packages/astro/test/fixtures/react-component/src/components/Pure.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/Pure.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/Research.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/Research.jsx
index 9ab83e5f3..9ab83e5f3 100644
--- a/packages/astro/test/fixtures/react-component/src/components/Research.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/Research.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/Suspense.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/Suspense.jsx
index 87dc82625..87dc82625 100644
--- a/packages/astro/test/fixtures/react-component/src/components/Suspense.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/Suspense.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/ThrowsAnError.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/ThrowsAnError.jsx
index cf970e38c..cf970e38c 100644
--- a/packages/astro/test/fixtures/react-component/src/components/ThrowsAnError.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/ThrowsAnError.jsx
diff --git a/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx b/packages/integrations/react/test/fixtures/react-component/src/components/TypeScriptComponent.tsx
index bde96da84..bde96da84 100644
--- a/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/TypeScriptComponent.tsx
diff --git a/packages/integrations/react/test/fixtures/react-component/src/components/WithChildren.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/WithChildren.jsx
new file mode 100644
index 000000000..500c0c694
--- /dev/null
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/WithChildren.jsx
@@ -0,0 +1,10 @@
+import React from 'react';
+
+export default function ({ children }) {
+ return (
+ <div>
+ <div className="with-children">{children}</div>
+ <div className="with-children-count">{children.length}</div>
+ </div>
+ );
+}
diff --git a/packages/astro/test/fixtures/react-component/src/components/WithId.jsx b/packages/integrations/react/test/fixtures/react-component/src/components/WithId.jsx
index 0abe91c72..0abe91c72 100644
--- a/packages/astro/test/fixtures/react-component/src/components/WithId.jsx
+++ b/packages/integrations/react/test/fixtures/react-component/src/components/WithId.jsx
diff --git a/packages/integrations/react/test/fixtures/react-component/src/pages/children.astro b/packages/integrations/react/test/fixtures/react-component/src/pages/children.astro
new file mode 100644
index 000000000..59595c266
--- /dev/null
+++ b/packages/integrations/react/test/fixtures/react-component/src/pages/children.astro
@@ -0,0 +1,14 @@
+---
+import WithChildren from '../components/WithChildren';
+---
+
+<html>
+ <head>
+ <!-- Head Stuff -->
+ </head>
+ <body>
+ <WithChildren>
+ <div>child 1</div><div>child 2</div>
+ </WithChildren>
+ </body>
+</html>
diff --git a/packages/astro/test/fixtures/react-component/src/pages/error-rendering.astro b/packages/integrations/react/test/fixtures/react-component/src/pages/error-rendering.astro
index 6984a6da5..6984a6da5 100644
--- a/packages/astro/test/fixtures/react-component/src/pages/error-rendering.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/pages/error-rendering.astro
diff --git a/packages/astro/test/fixtures/react-component/src/pages/index.astro b/packages/integrations/react/test/fixtures/react-component/src/pages/index.astro
index 3afd8233f..3afd8233f 100644
--- a/packages/astro/test/fixtures/react-component/src/pages/index.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/pages/index.astro
diff --git a/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro b/packages/integrations/react/test/fixtures/react-component/src/pages/pragma-comment.astro
index b3ddba639..b3ddba639 100644
--- a/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/pages/pragma-comment.astro
diff --git a/packages/astro/test/fixtures/react-component/src/pages/suspense.astro b/packages/integrations/react/test/fixtures/react-component/src/pages/suspense.astro
index 5a9d15644..5a9d15644 100644
--- a/packages/astro/test/fixtures/react-component/src/pages/suspense.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/pages/suspense.astro
diff --git a/packages/astro/test/fixtures/react-component/src/skipped-pages/forgot-import.astro b/packages/integrations/react/test/fixtures/react-component/src/skipped-pages/forgot-import.astro
index de5d319d9..de5d319d9 100644
--- a/packages/astro/test/fixtures/react-component/src/skipped-pages/forgot-import.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/skipped-pages/forgot-import.astro
diff --git a/packages/astro/test/fixtures/react-component/src/skipped-pages/window.astro b/packages/integrations/react/test/fixtures/react-component/src/skipped-pages/window.astro
index e780f3c44..e780f3c44 100644
--- a/packages/astro/test/fixtures/react-component/src/skipped-pages/window.astro
+++ b/packages/integrations/react/test/fixtures/react-component/src/skipped-pages/window.astro
diff --git a/packages/astro/test/react-component.test.js b/packages/integrations/react/test/react-component.test.js
index a6bb8cfae..da7fa018a 100644
--- a/packages/astro/test/react-component.test.js
+++ b/packages/integrations/react/test/react-component.test.js
@@ -1,13 +1,13 @@
import { expect } from 'chai';
import { load as cheerioLoad } from 'cheerio';
-import { isWindows, loadFixture } from './test-utils.js';
+import { isWindows, loadFixture } from '../../../astro/test/test-utils.js';
let fixture;
describe('React Components', () => {
before(async () => {
fixture = await loadFixture({
- root: './fixtures/react-component/',
+ root: new URL('./fixtures/react-component/', import.meta.url),
});
});
@@ -51,7 +51,7 @@ describe('React Components', () => {
// test 10: Should properly render children passed as props
const islandsWithChildren = $('.with-children');
expect(islandsWithChildren).to.have.lengthOf(2);
- expect($(islandsWithChildren[0]).html()).to.equal($(islandsWithChildren[1]).html());
+ expect($(islandsWithChildren[0]).html()).to.equal($(islandsWithChildren[1]).find('astro-slot').html());
// test 11: Should generate unique React.useId per island
const islandsWithId = $('.react-use-id');
@@ -99,12 +99,18 @@ describe('React Components', () => {
const $ = cheerioLoad(html);
expect($('#cloned').text()).to.equal('Cloned With Props');
});
+
+ it('Children are parsed as React components, can be manipulated', async () => {
+ const html = await fixture.readFile('/children/index.html');
+ const $ = cheerioLoad(html);
+ expect($(".with-children-count").text()).to.equal('2');
+ })
});
if (isWindows) return;
describe('dev', () => {
- /** @type {import('./test-utils').Fixture} */
+ /** @type {import('../../../astro/test/test-utils.js').Fixture} */
let devServer;
before(async () => {
diff --git a/packages/integrations/react/vnode-children.js b/packages/integrations/react/vnode-children.js
new file mode 100644
index 000000000..0c9d5e08d
--- /dev/null
+++ b/packages/integrations/react/vnode-children.js
@@ -0,0 +1,38 @@
+import { parse, walkSync, DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'
+import { createElement, Fragment } from 'react';
+
+export default function convert(children) {
+ const nodeMap = new WeakMap();
+ let doc = parse(children.toString().trim());
+ let root = createElement(Fragment, { children: [] });
+
+ walkSync(doc, (node, parent, index) => {
+ let newNode = {};
+ if (node.type === DOCUMENT_NODE) {
+ nodeMap.set(node, root);
+ } else if (node.type === ELEMENT_NODE) {
+ const { class: className, ...props } = node.attributes;
+ newNode = createElement(node.name, { ...props, className, children: [] });
+ nodeMap.set(node, newNode);
+ if (parent) {
+ const newParent = nodeMap.get(parent);
+ newParent.props.children[index] = newNode;
+
+ }
+ } else if (node.type === TEXT_NODE) {
+ newNode = node.value.trim();
+ if (newNode.trim()) {
+ if (parent) {
+ const newParent = nodeMap.get(parent);
+ if (parent.children.length === 1) {
+ newParent.props.children[0] = newNode;
+ } else {
+ newParent.props.children[index] = newNode;
+ }
+ }
+ }
+ }
+ });
+
+ return root.props.children;
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8eaf40cbe..d30fa57a6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3000,27 +3000,6 @@ importers:
specifier: ^1.7.6
version: 1.7.6
- packages/astro/test/fixtures/react-component:
- dependencies:
- '@astrojs/react':
- specifier: workspace:*
- version: link:../../../../integrations/react
- '@astrojs/vue':
- specifier: workspace:*
- version: link:../../../../integrations/vue
- astro:
- specifier: workspace:*
- version: link:../../..
- react:
- specifier: ^18.1.0
- version: 18.2.0
- react-dom:
- specifier: ^18.1.0
- version: 18.2.0(react@18.2.0)
- vue:
- specifier: ^3.3.4
- version: 3.3.4
-
packages/astro/test/fixtures/react-jsx-export:
dependencies:
react:
@@ -4787,6 +4766,9 @@ importers:
'@babel/plugin-transform-react-jsx':
specifier: ^7.22.5
version: 7.22.5(@babel/core@7.22.5)
+ ultrahtml:
+ specifier: ^1.2.0
+ version: 1.2.0
devDependencies:
'@types/react':
specifier: ^17.0.62
@@ -4800,12 +4782,42 @@ importers:
astro-scripts:
specifier: workspace:*
version: link:../../../scripts
+ chai:
+ specifier: ^4.3.7
+ version: 4.3.7
+ cheerio:
+ specifier: 1.0.0-rc.12
+ version: 1.0.0-rc.12
+ react:
+ specifier: ^18.1.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.1.0
+ version: 18.2.0(react@18.2.0)
+ vite:
+ specifier: ^4.4.6
+ version: 4.4.6(@types/node@18.16.18)(sass@1.63.4)
+
+ packages/integrations/react/test/fixtures/react-component:
+ dependencies:
+ '@astrojs/react':
+ specifier: workspace:*
+ version: link:../../..
+ '@astrojs/vue':
+ specifier: workspace:*
+ version: link:../../../../vue
+ astro:
+ specifier: workspace:*
+ version: link:../../../../../astro
react:
specifier: ^18.1.0
version: 18.2.0
react-dom:
specifier: ^18.1.0
version: 18.2.0(react@18.2.0)
+ vue:
+ specifier: ^3.3.4
+ version: 3.3.4
packages/integrations/sitemap:
dependencies:
@@ -17374,6 +17386,10 @@ packages:
resolution: {integrity: sha512-P24ulZdT9UKyQuKA1IApdAZ+F9lwruGvmKb4pG3+sMvR3CjN0pjawPnxuSABHQFB+XqnB35TVXzJPOBYjCv6Kw==}
dev: false
+ /ultrahtml@1.2.0:
+ resolution: {integrity: sha512-vxZM2yNvajRmCj/SknRYGNXk2tqiy6kRNvZjJLaleG3zJbSh/aNkOqD1/CVzypw8tyHyhpzYuwQgMMhUB4ZVNQ==}
+ dev: false
+
/unbox-primitive@1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
dependencies: