feat: support URL for markdoc nodes
This commit is contained in:
parent
0ab7d0dbd1
commit
321164503a
3 changed files with 55 additions and 38 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue