Render Custom Element Tag (#2473)
* Support rendering web components * nit: remove addition of script
This commit is contained in:
parent
0a112e1f56
commit
9f27941b4f
1 changed files with 32 additions and 1 deletions
|
@ -148,7 +148,7 @@ export async function renderComponent(result: SSRResult, displayName: string, Co
|
||||||
}
|
}
|
||||||
const probableRendererNames = guessRenderers(metadata.componentUrl);
|
const probableRendererNames = guessRenderers(metadata.componentUrl);
|
||||||
|
|
||||||
if (Array.isArray(renderers) && renderers.length === 0 && typeof Component !== 'string') {
|
if (Array.isArray(renderers) && renderers.length === 0 && typeof Component !== 'string' && !HTMLElement.isPrototypeOf(Component as object)) {
|
||||||
const message = `Unable to render ${metadata.displayName}!
|
const message = `Unable to render ${metadata.displayName}!
|
||||||
|
|
||||||
There are no \`renderers\` set in your \`astro.config.mjs\` file.
|
There are no \`renderers\` set in your \`astro.config.mjs\` file.
|
||||||
|
@ -165,6 +165,12 @@ Did you mean to enable ${formatList(probableRendererNames.map((r) => '`' + r + '
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!renderer && HTMLElement.isPrototypeOf(Component as object)) {
|
||||||
|
const output = renderHTMLElement(result, Component as typeof HTMLElement, _props, slots);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Attempt: use explicitly passed renderer name
|
// Attempt: use explicitly passed renderer name
|
||||||
if (metadata.hydrateArgs) {
|
if (metadata.hydrateArgs) {
|
||||||
|
@ -434,6 +440,31 @@ export async function renderAstroComponent(component: InstanceType<typeof AstroC
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function renderHTMLElement(result: SSRResult, constructor: typeof HTMLElement, props: any, children: any) {
|
||||||
|
const name = getHTMLElementName(constructor);
|
||||||
|
|
||||||
|
let attrHTML = '';
|
||||||
|
|
||||||
|
for (const attr in props) {
|
||||||
|
attrHTML += ` ${attr}="${toAttributeString(await props[attr])}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
children = await children;
|
||||||
|
children = children == null ? children : '';
|
||||||
|
|
||||||
|
const html = `<${name}${attrHTML}>${children}</${name}>`;
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHTMLElementName(constructor: typeof HTMLElement) {
|
||||||
|
const definedName = (customElements as CustomElementRegistry & { getName(_constructor: typeof HTMLElement): string }).getName(constructor);
|
||||||
|
if (definedName) return definedName
|
||||||
|
|
||||||
|
const assignedName = constructor.name.replace(/^HTML|Element$/g, '').replace(/[A-Z]/g, '-$&').toLowerCase().replace(/^-/, 'html-')
|
||||||
|
return assignedName
|
||||||
|
}
|
||||||
|
|
||||||
function renderElement(name: string, { props: _props, children = '' }: SSRElement) {
|
function renderElement(name: string, { props: _props, children = '' }: SSRElement) {
|
||||||
// Do not print `hoist`, `lang`, `global`
|
// Do not print `hoist`, `lang`, `global`
|
||||||
const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props;
|
const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props;
|
||||||
|
|
Loading…
Reference in a new issue