feat: support URL for markdoc nodes

This commit is contained in:
bholmesdev 2023-06-07 16:01:38 -04:00 committed by bholmesdev
parent 0ab7d0dbd1
commit 321164503a
3 changed files with 55 additions and 38 deletions

View file

@ -9,7 +9,7 @@ import _Markdoc from '@markdoc/markdoc';
import type { AstroInstance } from 'astro'; import type { AstroInstance } from 'astro';
import { heading } from './heading-ids.js'; import { heading } from './heading-ids.js';
type Render = AstroInstance['default'] | URL | string; export type Render = AstroInstance['default'] | URL | string;
export type AstroMarkdocConfig<C extends Record<string, any> = Record<string, any>> = Omit< export type AstroMarkdocConfig<C extends Record<string, any> = Record<string, any>> = Omit<
MarkdocConfig, MarkdocConfig,

View file

@ -1,6 +1,6 @@
import type { MarkdownHeading } from '@astrojs/markdown-remark'; import type { MarkdownHeading } from '@astrojs/markdown-remark';
import type { AstroInstance } from 'astro'; 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 type { AstroMarkdocConfig } from './config.js';
import { setupHeadingConfig } from './heading-ids.js'; import { setupHeadingConfig } from './heading-ids.js';
@ -68,23 +68,19 @@ function mergeConfig(configA: AstroMarkdocConfig, configB: AstroMarkdocConfig):
} }
export function resolveComponentImports( export function resolveComponentImports(
markdocConfig: AstroMarkdocConfig, markdocConfig: Required<Pick<AstroMarkdocConfig, 'tags' | 'nodes'>>,
tagComponentMap: Record<string, AstroInstance['default']> tagComponentMap: Record<string, AstroInstance['default']>,
nodeComponentMap: Record<NodeType, AstroInstance['default']>
) { ) {
const resolvedTags = { ...markdocConfig.tags }; for (const [tag, render] of Object.entries(tagComponentMap)) {
for (const [tagName, tagConfig] of Object.entries(resolvedTags)) { const config = markdocConfig.tags[tag];
if (tagName in tagComponentMap) { if (config) config.render = render;
resolvedTags[tagName] = {
...tagConfig,
render: tagComponentMap[tagName],
};
} }
for (const [node, render] of Object.entries(nodeComponentMap)) {
const config = markdocConfig.nodes[node as NodeType];
if (config) config.render = render;
} }
console.log('resolvedTags', resolvedTags); return markdocConfig;
return {
...markdocConfig,
tags: resolvedTags,
};
} }
/** /**

View file

@ -2,6 +2,9 @@ import type { AstroConfig } from 'astro';
import type { Plugin } from 'vite'; import type { Plugin } from 'vite';
import type { PluginContext } from 'rollup'; import type { PluginContext } from 'rollup';
import { loadMarkdocConfig } from './load-config.js'; 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 markdocConfigId = 'astro:markdoc-config';
export const resolvedMarkdocConfigId = '\x00' + markdocConfigId; export const resolvedMarkdocConfigId = '\x00' + markdocConfigId;
@ -24,31 +27,49 @@ export function vitePluginMarkdocConfig({ astroConfig }: { astroConfig: AstroCon
return `export default {}`; return `export default {}`;
} }
const { config, fileUrl } = markdocConfigResult; const { config, fileUrl } = markdocConfigResult;
let componentPathnameByTag: Record<string, string> = {}; const tagRenderPathnameMap = getRenderUrlMap(config.tags ?? {});
const { tags = {}, nodes = {} /* TODO: nodes */ } = config; const nodeRenderPathnameMap = getRenderUrlMap(config.nodes ?? {});
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'; const code = `import { resolveComponentImports } from '@astrojs/markdoc/runtime';
import markdocConfig from ${JSON.stringify(fileUrl.pathname)}; import markdocConfig from ${JSON.stringify(fileUrl.pathname)};
${stringifiedComponentImports}; ${getStringifiedImports(tagRenderPathnameMap, 'Tag')};
${getStringifiedImports(nodeRenderPathnameMap, 'Node')};
const tagComponentMap = ${stringifiedComponentMap}; const tagComponentMap = ${getStringifiedMap(tagRenderPathnameMap, 'Tag')};
export default resolveComponentImports(markdocConfig, tagComponentMap);`; const nodeComponentMap = ${getStringifiedMap(nodeRenderPathnameMap, 'Node')};
export default resolveComponentImports(markdocConfig, tagComponentMap, nodeComponentMap);`;
console.log('$$$markdoc-config', code); console.log('$$$markdoc-config', code);
return code; return code;
}, },
}; };
} }
function getRenderUrlMap(tagsOrNodes: Record<string, Schema<AstroMarkdocConfig, Render>>) {
const renderPathnameMap: Record<string, string> = {};
for (const [name, value] of Object.entries(tagsOrNodes)) {
if (value.render instanceof URL) {
renderPathnameMap[name] = value.render.pathname;
}
}
return renderPathnameMap;
}
function getStringifiedImports(renderUrlMap: Record<string, string>, 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<string, string>, componentNamePrefix: string) {
let stringifiedComponentMap = '{';
for (const key in renderUrlMap) {
stringifiedComponentMap += `${key}: ${componentNamePrefix + key},\n`;
}
stringifiedComponentMap += '}';
return stringifiedComponentMap;
}