diff --git a/packages/integrations/markdoc/src/config.ts b/packages/integrations/markdoc/src/config.ts index 60d4c5ff6..07615e8bc 100644 --- a/packages/integrations/markdoc/src/config.ts +++ b/packages/integrations/markdoc/src/config.ts @@ -9,7 +9,7 @@ import _Markdoc from '@markdoc/markdoc'; import type { AstroInstance } from 'astro'; import { heading } from './heading-ids.js'; -type Render = AstroInstance['default'] | URL | string; +export type Render = AstroInstance['default'] | URL | string; export type AstroMarkdocConfig = Record> = Omit< MarkdocConfig, diff --git a/packages/integrations/markdoc/src/runtime.ts b/packages/integrations/markdoc/src/runtime.ts index 56cb36886..035cb8856 100644 --- a/packages/integrations/markdoc/src/runtime.ts +++ b/packages/integrations/markdoc/src/runtime.ts @@ -1,6 +1,6 @@ import type { MarkdownHeading } from '@astrojs/markdown-remark'; import type { AstroInstance } from 'astro'; -import Markdoc, { type RenderableTreeNode } from '@markdoc/markdoc'; +import Markdoc, { type NodeType, type RenderableTreeNode } from '@markdoc/markdoc'; import type { AstroMarkdocConfig } from './config.js'; import { setupHeadingConfig } from './heading-ids.js'; @@ -68,23 +68,19 @@ function mergeConfig(configA: AstroMarkdocConfig, configB: AstroMarkdocConfig): } export function resolveComponentImports( - markdocConfig: AstroMarkdocConfig, - tagComponentMap: Record + markdocConfig: Required>, + tagComponentMap: Record, + nodeComponentMap: Record ) { - const resolvedTags = { ...markdocConfig.tags }; - for (const [tagName, tagConfig] of Object.entries(resolvedTags)) { - if (tagName in tagComponentMap) { - resolvedTags[tagName] = { - ...tagConfig, - render: tagComponentMap[tagName], - }; - } + for (const [tag, render] of Object.entries(tagComponentMap)) { + const config = markdocConfig.tags[tag]; + if (config) config.render = render; } - console.log('resolvedTags', resolvedTags); - return { - ...markdocConfig, - tags: resolvedTags, - }; + for (const [node, render] of Object.entries(nodeComponentMap)) { + const config = markdocConfig.nodes[node as NodeType]; + if (config) config.render = render; + } + return markdocConfig; } /** diff --git a/packages/integrations/markdoc/src/vite-plugin-config.ts b/packages/integrations/markdoc/src/vite-plugin-config.ts index b911377fb..b4eb1c65b 100644 --- a/packages/integrations/markdoc/src/vite-plugin-config.ts +++ b/packages/integrations/markdoc/src/vite-plugin-config.ts @@ -2,6 +2,9 @@ import type { AstroConfig } from 'astro'; import type { Plugin } from 'vite'; import type { PluginContext } from 'rollup'; import { loadMarkdocConfig } from './load-config.js'; +import type { AstroMarkdocConfig } from './config.js'; +import type { Schema } from '@markdoc/markdoc'; +import type { Render } from './config.js'; export const markdocConfigId = 'astro:markdoc-config'; export const resolvedMarkdocConfigId = '\x00' + markdocConfigId; @@ -24,31 +27,49 @@ export function vitePluginMarkdocConfig({ astroConfig }: { astroConfig: AstroCon return `export default {}`; } const { config, fileUrl } = markdocConfigResult; - let componentPathnameByTag: Record = {}; - const { tags = {}, nodes = {} /* TODO: nodes */ } = config; - for (const [name, value] of Object.entries(tags)) { - if (value.render instanceof URL) { - componentPathnameByTag[name] = value.render.pathname; - } - } - let stringifiedComponentImports = ''; - let stringifiedComponentMap = '{'; - for (const [tag, componentPathname] of Object.entries(componentPathnameByTag)) { - stringifiedComponentImports += `import ${tag} from ${JSON.stringify( - componentPathname + '?astroPropagatedAssets' - )};\n`; - stringifiedComponentMap += `${tag},\n`; - } - stringifiedComponentMap += '}'; - const code = `import { resolveComponentImports } from '@astrojs/markdoc/runtime'; - import markdocConfig from ${JSON.stringify(fileUrl.pathname)}; - ${stringifiedComponentImports}; + const tagRenderPathnameMap = getRenderUrlMap(config.tags ?? {}); + const nodeRenderPathnameMap = getRenderUrlMap(config.nodes ?? {}); - const tagComponentMap = ${stringifiedComponentMap}; - export default resolveComponentImports(markdocConfig, tagComponentMap);`; + const code = `import { resolveComponentImports } from '@astrojs/markdoc/runtime'; + import markdocConfig from ${JSON.stringify(fileUrl.pathname)}; + ${getStringifiedImports(tagRenderPathnameMap, 'Tag')}; + ${getStringifiedImports(nodeRenderPathnameMap, 'Node')}; + + const tagComponentMap = ${getStringifiedMap(tagRenderPathnameMap, 'Tag')}; + const nodeComponentMap = ${getStringifiedMap(nodeRenderPathnameMap, 'Node')}; + export default resolveComponentImports(markdocConfig, tagComponentMap, nodeComponentMap);`; console.log('$$$markdoc-config', code); return code; }, }; } + +function getRenderUrlMap(tagsOrNodes: Record>) { + const renderPathnameMap: Record = {}; + for (const [name, value] of Object.entries(tagsOrNodes)) { + if (value.render instanceof URL) { + renderPathnameMap[name] = value.render.pathname; + } + } + return renderPathnameMap; +} + +function getStringifiedImports(renderUrlMap: Record, componentNamePrefix: string) { + let stringifiedComponentImports = ''; + for (const [key, renderUrl] of Object.entries(renderUrlMap)) { + stringifiedComponentImports += `import ${componentNamePrefix + key} from ${JSON.stringify( + renderUrl + '?astroPropagatedAssets' + )};\n`; + } + return stringifiedComponentImports; +} + +function getStringifiedMap(renderUrlMap: Record, componentNamePrefix: string) { + let stringifiedComponentMap = '{'; + for (const key in renderUrlMap) { + stringifiedComponentMap += `${key}: ${componentNamePrefix + key},\n`; + } + stringifiedComponentMap += '}'; + return stringifiedComponentMap; +}