refactor: move markdoc transform to build time
This commit is contained in:
parent
c7e4236ed7
commit
d66ee0dcd0
4 changed files with 40 additions and 22 deletions
|
@ -3,5 +3,20 @@ import markdoc from '@astrojs/markdoc';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [markdoc()],
|
integrations: [
|
||||||
|
markdoc({
|
||||||
|
variables: {
|
||||||
|
revealSecret: true,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
aside: {
|
||||||
|
render: 'Aside',
|
||||||
|
attributes: {
|
||||||
|
type: { type: String },
|
||||||
|
title: { type: String },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,19 +11,6 @@ const { Content } = await entry.render();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Content
|
<Content
|
||||||
config={{
|
|
||||||
// Accepts all Markdoc configuration options
|
|
||||||
// See https://markdoc.dev/docs/config#full-example
|
|
||||||
tags: {
|
|
||||||
aside: {
|
|
||||||
render: 'Aside',
|
|
||||||
attributes: {
|
|
||||||
type: { type: String },
|
|
||||||
title: { type: String },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
components={{
|
components={{
|
||||||
// Pass a mapping from the component name
|
// Pass a mapping from the component name
|
||||||
// To an Astro or UI component import
|
// To an Astro or UI component import
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
import type { AstroIntegration } from 'astro';
|
import type { AstroIntegration } from 'astro';
|
||||||
import type { InlineConfig } from 'vite';
|
import type { InlineConfig } from 'vite';
|
||||||
import type { Config as _MarkdocConfig } from '@markdoc/markdoc';
|
import type { Config, Config as _MarkdocConfig } from '@markdoc/markdoc';
|
||||||
import _Markdoc from '@markdoc/markdoc';
|
import _Markdoc from '@markdoc/markdoc';
|
||||||
import { parseFrontmatter } from './utils.js';
|
import { parseFrontmatter } from './utils.js';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
|
||||||
export default function markdoc(): AstroIntegration {
|
export default function markdoc(markdocConfig: Config): AstroIntegration {
|
||||||
|
const entryBodyByFileIdCache = new Map<string, string>();
|
||||||
return {
|
return {
|
||||||
name: '@astrojs/markdoc',
|
name: '@astrojs/markdoc',
|
||||||
hooks: {
|
hooks: {
|
||||||
'astro:config:setup': async ({ updateConfig, config, addContentEntryType, command }: any) => {
|
'astro:config:setup': async ({ updateConfig, config, addContentEntryType }: any) => {
|
||||||
const contentEntryType = {
|
const contentEntryType = {
|
||||||
extensions: ['.mdoc'],
|
extensions: ['.mdoc'],
|
||||||
async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) {
|
getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) {
|
||||||
const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
|
const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
|
||||||
|
entryBodyByFileIdCache.set(fileUrl.pathname, parsed.content);
|
||||||
return {
|
return {
|
||||||
data: parsed.data,
|
data: parsed.data,
|
||||||
body: parsed.content,
|
body: parsed.content,
|
||||||
|
@ -35,9 +37,24 @@ export default function markdoc(): AstroIntegration {
|
||||||
name: '@astrojs/markdoc',
|
name: '@astrojs/markdoc',
|
||||||
async transform(code, id) {
|
async transform(code, id) {
|
||||||
if (!id.endsWith('.mdoc')) return;
|
if (!id.endsWith('.mdoc')) return;
|
||||||
return `import { jsx as h } from 'astro/jsx-runtime';\nimport { Markdoc } from '@astrojs/markdoc';\nimport { Renderer } from '@astrojs/markdoc/components';\nexport const body = ${JSON.stringify(
|
|
||||||
code
|
const body = entryBodyByFileIdCache.get(id);
|
||||||
)};\nexport function getParsed() { return Markdoc.parse(body); }\nexport function getTransformed(inlineConfig) { return Markdoc.transform(getParsed(), inlineConfig) }\nexport async function Content ({ config, components }) { return h(Renderer, { content: getTransformed(config), components }); }\nContent[Symbol.for('astro.needsHeadRendering')] = true;`;
|
if (!body) {
|
||||||
|
// Cache entry should exist if `getCollection()` was called
|
||||||
|
// (see `getEntryInfo()` above)
|
||||||
|
// If not, the user probably tried to import directly.
|
||||||
|
throw new Error(
|
||||||
|
`Unable to render ${JSON.stringify(
|
||||||
|
id.replace(config.root.pathname, '')
|
||||||
|
)}. If you tried to import this file directly, please use a Content Collection query instead. See https://docs.astro.build/en/guides/content-collections/#rendering-content-to-html for more information.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const rawAst = Markdoc.parse(body);
|
||||||
|
const ast = Markdoc.transform(rawAst, markdocConfig);
|
||||||
|
|
||||||
|
return `import { jsx as h } from 'astro/jsx-runtime';\nimport { Markdoc } from '@astrojs/markdoc';\nimport { Renderer } from '@astrojs/markdoc/components';\nconst ast = ${JSON.stringify(
|
||||||
|
ast
|
||||||
|
)};\nexport async function Content ({ components }) { return h(Renderer, { content: ast, components }); }\nContent[Symbol.for('astro.needsHeadRendering')] = true;`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -12,7 +12,6 @@ declare module 'astro:content' {
|
||||||
interface Render {
|
interface Render {
|
||||||
'.mdoc': Promise<{
|
'.mdoc': Promise<{
|
||||||
Content(props: {
|
Content(props: {
|
||||||
config?: import('@astrojs/markdoc').MarkdocConfig;
|
|
||||||
components?: Record<string, ComponentRenderer>;
|
components?: Record<string, ComponentRenderer>;
|
||||||
}): import('astro').MarkdownInstance<{}>['Content'];
|
}): import('astro').MarkdownInstance<{}>['Content'];
|
||||||
}>;
|
}>;
|
||||||
|
|
Loading…
Reference in a new issue