wip: support true react vnodes in renderer
This commit is contained in:
parent
4ce2ba972a
commit
304dbada53
4 changed files with 58 additions and 2 deletions
|
@ -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",
|
||||
|
|
|
@ -43,6 +43,12 @@ async function check(Component, props, children) {
|
|||
return React.createElement('div');
|
||||
}
|
||||
|
||||
if (props['use:vnode']) {
|
||||
const convert = await import('./vnode-children.js').then(mod => mod.default);
|
||||
delete props['use:vnode'];
|
||||
children = convert(children);
|
||||
}
|
||||
|
||||
await renderToStaticMarkup(Tester, props, children, {});
|
||||
|
||||
if (error) {
|
||||
|
@ -85,7 +91,11 @@ async function renderToStaticMarkup(Component, props, { default: children, ...sl
|
|||
...slots,
|
||||
};
|
||||
const newChildren = children ?? props.children;
|
||||
if (newChildren != null) {
|
||||
if (props['use:vnode']) {
|
||||
const convert = await import('./vnode-children.js').then(mod => mod.default);
|
||||
delete props['use:vnode'];
|
||||
newProps.children = convert(children)
|
||||
} else if (newChildren != null) {
|
||||
newProps.children = React.createElement(StaticHtml, {
|
||||
hydrate: needsHydration(metadata),
|
||||
value: newChildren,
|
||||
|
|
38
packages/integrations/react/vnode-children.js
Normal file
38
packages/integrations/react/vnode-children.js
Normal file
|
@ -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.default.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;
|
||||
}
|
|
@ -4720,6 +4720,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
|
||||
|
@ -17114,6 +17117,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:
|
||||
|
|
Loading…
Reference in a new issue