From 1d10dd210ab8bf4ffae452b15df0ffdb74057dc5 Mon Sep 17 00:00:00 2001 From: Giancarlo Buomprisco Date: Thu, 22 Aug 2024 04:34:10 +0800 Subject: [PATCH] Refactor to support custom Markdoc components (#52) * Refactor to support custom Markdoc components Introduced a new file for custom Markdoc components and updated the client to render Markdoc content using React components. Modified content renderer to handle React nodes instead of dangerously setting inner HTML. * Add custom Markdoc tags support in Keystatic Introduced `CustomMarkdocTags` for defining user tags. Updated `transform` to accommodate the new custom tags, enhancing tag customization in the CMS. --- .../cms/keystatic/src/content-renderer.tsx | 2 +- .../cms/keystatic/src/custom-components.tsx | 32 +++++++++++++++++++ .../cms/keystatic/src/keystatic-client.ts | 18 +++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 packages/cms/keystatic/src/custom-components.tsx diff --git a/packages/cms/keystatic/src/content-renderer.tsx b/packages/cms/keystatic/src/content-renderer.tsx index e25c25729..0fceb95af 100644 --- a/packages/cms/keystatic/src/content-renderer.tsx +++ b/packages/cms/keystatic/src/content-renderer.tsx @@ -1,3 +1,3 @@ export function KeystaticContentRenderer(props: { content: unknown }) { - return
; + return
{props.content as React.ReactNode}
; } diff --git a/packages/cms/keystatic/src/custom-components.tsx b/packages/cms/keystatic/src/custom-components.tsx new file mode 100644 index 000000000..976c48dbd --- /dev/null +++ b/packages/cms/keystatic/src/custom-components.tsx @@ -0,0 +1,32 @@ +/** + * @name CustomMarkdocComponents + * @description Custom components for Markdoc. Please define your custom components here. + * @example + * + * ```ts + * function Youtube(props: { src: string }) { ... } + * + * export const CustomMarkdocComponents: Record> = { + * Youtube, + * }; + */ +export const CustomMarkdocComponents: Record< + string, + React.ComponentType +> = { + // define your custom components here +}; + +/** + * @name CustomMarkdocTags + * @description Custom tags for Markdoc. Please define your custom tags here. + * @example + * export const CustomMarkdocTags = { + * youtube: { + * render: "Youtube", + * } + * } + */ +export const CustomMarkdocTags = { + // define your custom tags here +}; diff --git a/packages/cms/keystatic/src/keystatic-client.ts b/packages/cms/keystatic/src/keystatic-client.ts index bdd4445b5..bab46f055 100644 --- a/packages/cms/keystatic/src/keystatic-client.ts +++ b/packages/cms/keystatic/src/keystatic-client.ts @@ -1,6 +1,12 @@ +import React from 'react'; + import { Cms, CmsClient } from '@kit/cms'; import { createKeystaticReader } from './create-reader'; +import { + CustomMarkdocComponents, + CustomMarkdocTags, +} from './custom-components'; import { PostEntryProps } from './keystatic.config'; export function createKeystaticClient() { @@ -158,8 +164,14 @@ class KeystaticClient implements CmsClient { : new Date(); const markdoc = await item.entry.content(); - const content = transform(markdoc.node); - const html = renderers.html(content); + + const content = transform(markdoc.node, { + tags: CustomMarkdocTags, + }); + + const html = renderers.react(content, React, { + components: CustomMarkdocComponents, + }); return { id: item.slug, @@ -168,7 +180,7 @@ class KeystaticClient implements CmsClient { slug: item.slug, description: item.entry.description, publishedAt: publishedAt.toISOString(), - content: html, + content: html as string, image: item.entry.image ?? undefined, status: item.entry.status, categories: