import type { RenderableTreeNode } from '@markdoc/markdoc'; import Markdoc from '@markdoc/markdoc'; import type { AstroInstance } from 'astro'; import type { HTMLString } from 'astro/runtime/server/index.js'; import { createComponent, createHeadAndContent, isHTMLString, render, renderComponent, renderScriptElement, renderTemplate, renderUniqueStylesheet, unescapeHTML, } from 'astro/runtime/server/index.js'; export type TreeNode = | { type: 'text'; content: string | HTMLString; } | { type: 'component'; component: AstroInstance['default']; collectedLinks?: string[]; collectedStyles?: string[]; collectedScripts?: string[]; props: Record; children: TreeNode[]; } | { type: 'element'; tag: string; attributes: Record; children: TreeNode[]; }; export const ComponentNode = createComponent({ factory(result: any, { treeNode }: { treeNode: TreeNode }) { if (treeNode.type === 'text') return render`${treeNode.content}`; const slots = { default: () => render`${treeNode.children.map((child) => renderComponent(result, 'ComponentNode', ComponentNode, { treeNode: child }) )}`, }; if (treeNode.type === 'component') { let styles = '', links = '', scripts = ''; if (Array.isArray(treeNode.collectedStyles)) { styles = treeNode.collectedStyles .map((style: any) => renderUniqueStylesheet(result, { type: 'inline', content: style, }) ) .join(''); } if (Array.isArray(treeNode.collectedLinks)) { links = treeNode.collectedLinks .map((link: any) => { return renderUniqueStylesheet(result, { type: 'external', src: link[0] === '/' ? link : '/' + link, }); }) .join(''); } if (Array.isArray(treeNode.collectedScripts)) { scripts = treeNode.collectedScripts .map((script: any) => renderScriptElement(script)) .join(''); } const head = unescapeHTML(styles + links + scripts); let headAndContent = createHeadAndContent( head, renderTemplate`${renderComponent( result, treeNode.component.name, treeNode.component, treeNode.props, slots )}` ); // Let the runtime know that this component is being used. result._metadata.propagators.add({ init() { return headAndContent; }, }); return headAndContent; } return renderComponent(result, treeNode.tag, treeNode.tag, treeNode.attributes, slots); }, propagation: 'self', }); export async function createTreeNode(node: RenderableTreeNode): Promise { if (isHTMLString(node)) { return { type: 'text', content: node as HTMLString }; } else if (typeof node === 'string' || typeof node === 'number') { return { type: 'text', content: String(node) }; } else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) { return { type: 'text', content: '' }; } const children = await Promise.all(node.children.map((child) => createTreeNode(child))); if (typeof node.name === 'function') { const component = node.name; const props = node.attributes; return { type: 'component', component, props, children, }; } else if (isPropagatedAssetsModule(node.name)) { const { collectedStyles, collectedLinks, collectedScripts } = node.name; const component = (await node.name.getMod()).default; const props = node.attributes; return { type: 'component', component, collectedStyles, collectedLinks, collectedScripts, props, children, }; } else { return { type: 'element', tag: node.name, attributes: node.attributes, children, }; } } type PropagatedAssetsModule = { __astroPropagation: true; getMod: () => Promise; collectedStyles: string[]; collectedLinks: string[]; collectedScripts: string[]; }; function isPropagatedAssetsModule(module: any): module is PropagatedAssetsModule { return typeof module === 'object' && module != null && '__astroPropagation' in module; } ant to pass the position arrays by const ref when assigning the...Gravatar Andrew Myers 2-16/+15 2020-01-24fix shadowing warningGravatar Andrew Myers 1-11/+13 2020-01-24Docs: Fix Example Download LinksGravatar Axel Huebl 1-9/+9 2020-01-24run_test.sh: back to single brackets in conditional expression (safest practi...Gravatar Edoardo Zoni 1-1/+1 2020-01-23OCD fix: Laser sectionGravatar L. Diana Amorim 1-1/+1 2020-01-23Minor fix to slice parameters in DocsGravatar L. Diana Amorim 1-1/+1 2020-01-23Change do_not_push to be species specific and add corresponding documentation.Gravatar Yinjian Zhao 3-1/+5 2020-01-23External particle fields: correct documentationGravatar Remi Lehe 1-11/+11 2020-01-23Update CONTRIBUTING.md: how to run single testsGravatar Edoardo Zoni 1-1/+6 2020-01-23run_test.sh: fix parser to handle both single and multiple tests (or no input).Gravatar Edoardo Zoni 1-5/+13 2020-01-22run_test.sh: use double bracket conditional compound command [[...]] (otherwi...Gravatar Edoardo Zoni 1-1/+1 2020-01-22run_test.sh: parse command line arguments to run single test (does not yet wo...Gravatar Edoardo Zoni 1-1/+5 2020-01-22Interpolate Current: Fix Shadow WarningGravatar Axel Huebl 1-2/+2 2020-01-22Address Review Comments by @MaxThevenetGravatar Axel Huebl 1-10/+8 2020-01-21openPMD: Add Particle `id`Gravatar Axel Huebl 2-18/+43 2020-01-21openPMD: ED-PIC Extension SupportGravatar Axel Huebl 4-85/+302 2020-01-21WarpX: authors input optionGravatar Axel Huebl 4-0/+12