diff --git a/packages/integrations/markdoc/components/astroNode.ts b/packages/integrations/markdoc/components/astroNode.ts index 0e9ce0fb0..bd7bc5e03 100644 --- a/packages/integrations/markdoc/components/astroNode.ts +++ b/packages/integrations/markdoc/components/astroNode.ts @@ -1,6 +1,7 @@ import type { AstroInstance } from 'astro'; import type { RenderableTreeNode } from '@markdoc/markdoc'; import Markdoc from '@markdoc/markdoc'; +import z from 'zod'; export type AstroNode = | string @@ -19,18 +20,18 @@ export function createAstroNode( node: RenderableTreeNode, components: Record = {} ): AstroNode { + components = validateComponents(components); + if (typeof node === 'string' || typeof node === 'number') { return String(node); } else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) { return ''; } - if (node.name in components) { + if (isCapitalized(node.name) && node.name in components) { const component = components[node.name]; const props = node.attributes; - console.log({ node, component, props, components }); - const children = node.children.map((child) => createAstroNode(child, components)); return { @@ -46,3 +47,32 @@ export function createAstroNode( }; } } + +function validateComponents(components: Record) { + return z + .record( + z + .string() + .min(1, toComponentsKeyErrorMsg('Component name cannot be empty.')) + .refine( + (value) => isCapitalized(value), + (value) => ({ + message: toComponentsKeyErrorMsg( + `Component name must be capitalized (received ${JSON.stringify( + value + )}). If you want to render HTML elements as components, try using a Markdoc node [TODO: DOCS LINK]` + ), + }) + ), + z.any() + ) + .parse(components); +} + +function toComponentsKeyErrorMsg(msg: string) { + return '[Markdoc] Invalid "components" prop: ' + msg; +} + +function isCapitalized(str: string) { + return str.length > 0 && str[0] === str[0].toUpperCase(); +}