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.
This commit is contained in:
Giancarlo Buomprisco
2024-08-22 04:34:10 +08:00
committed by GitHub
parent 2afa736f4c
commit 1d10dd210a
3 changed files with 48 additions and 4 deletions

View File

@@ -1,3 +1,3 @@
export function KeystaticContentRenderer(props: { content: unknown }) {
return <div dangerouslySetInnerHTML={{ __html: props.content as string }} />;
return <div>{props.content as React.ReactNode}</div>;
}

View File

@@ -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<string, React.ComponentType<never>> = {
* Youtube,
* };
*/
export const CustomMarkdocComponents: Record<
string,
React.ComponentType<never>
> = {
// 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
};

View File

@@ -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: