Integrate Markdoc library with Keystatic CMS.
The commit introduces the '@markdoc/markdoc' library to the Keystatic CMS. It modifies related functions and components such as 'KeystaticDocumentRenderer' and 'keystatic-client' to transform and render content using Markdoc. Additionally, the commit refactors 'keystatic.config.ts' file for more legible content field setup and adds related dependencies in the package.
This commit is contained in:
@@ -16,7 +16,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@keystatic/core": "0.5.14",
|
"@keystatic/core": "0.5.14",
|
||||||
"@keystatic/next": "5.0.0"
|
"@keystatic/next": "5.0.0",
|
||||||
|
"@markdoc/markdoc": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kit/cms": "workspace:^",
|
"@kit/cms": "workspace:^",
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
"@kit/tsconfig": "workspace:*",
|
"@kit/tsconfig": "workspace:*",
|
||||||
"@kit/ui": "workspace:^",
|
"@kit/ui": "workspace:^",
|
||||||
"@types/node": "^20.12.8",
|
"@types/node": "^20.12.8",
|
||||||
|
"@types/react": "^18.3.1",
|
||||||
|
"react": "18.3.1",
|
||||||
"zod": "^3.23.6"
|
"zod": "^3.23.6"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { DocumentElement } from '@keystatic/core';
|
import * as React from 'react';
|
||||||
import { DocumentRenderer } from '@keystatic/core/renderer';
|
|
||||||
|
|
||||||
export function KeystaticDocumentRenderer(props: { content: unknown }) {
|
import Markdoc from '@markdoc/markdoc';
|
||||||
return <DocumentRenderer document={props.content as DocumentElement[]} />;
|
|
||||||
|
export function KeystaticDocumentRenderer({ content }: { content: unknown }) {
|
||||||
|
return Markdoc.renderers.react(content as string, React);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import Markdoc from '@markdoc/markdoc';
|
||||||
|
|
||||||
import { Cms, CmsClient } from '@kit/cms';
|
import { Cms, CmsClient } from '@kit/cms';
|
||||||
|
|
||||||
import { createKeystaticReader } from './create-reader';
|
import { createKeystaticReader } from './create-reader';
|
||||||
@@ -138,7 +140,8 @@ class KeystaticClient implements CmsClient {
|
|||||||
? new Date(item.entry.publishedAt)
|
? new Date(item.entry.publishedAt)
|
||||||
: new Date();
|
: new Date();
|
||||||
|
|
||||||
const content = await item.entry.content();
|
const markdoc = await item.entry.content();
|
||||||
|
const content = Markdoc.transform(markdoc.node);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: item.slug,
|
id: item.slug,
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
import { collection, config, fields } from '@keystatic/core';
|
import {
|
||||||
|
CloudConfig,
|
||||||
|
GitHubConfig,
|
||||||
|
LocalConfig,
|
||||||
|
collection,
|
||||||
|
config,
|
||||||
|
fields,
|
||||||
|
} from '@keystatic/core';
|
||||||
import { Entry } from '@keystatic/core/reader';
|
import { Entry } from '@keystatic/core/reader';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
type ZodOutputFor<T> = z.ZodType<T, z.ZodTypeDef, unknown>;
|
||||||
|
|
||||||
const local = z.object({
|
const local = z.object({
|
||||||
kind: z.literal('local'),
|
kind: z.literal('local'),
|
||||||
});
|
}) satisfies ZodOutputFor<LocalConfig['storage']>;
|
||||||
|
|
||||||
const cloud = z.object({
|
const cloud = z.object({
|
||||||
kind: z.literal('cloud'),
|
kind: z.literal('cloud'),
|
||||||
project: z.string(),
|
project: z.string(),
|
||||||
});
|
}) satisfies ZodOutputFor<CloudConfig['storage']>;
|
||||||
|
|
||||||
const github = z.object({
|
const github = z.object({
|
||||||
kind: z.literal('github'),
|
kind: z.literal('github'),
|
||||||
@@ -19,7 +28,7 @@ const github = z.object({
|
|||||||
githubToken: z.string({
|
githubToken: z.string({
|
||||||
required_error: 'Please provide a GitHub token',
|
required_error: 'Please provide a GitHub token',
|
||||||
}),
|
}),
|
||||||
});
|
}) satisfies ZodOutputFor<GitHubConfig['storage']>;
|
||||||
|
|
||||||
const storage = z.union([local, cloud, github]).parse({
|
const storage = z.union([local, cloud, github]).parse({
|
||||||
kind: process.env.KEYSTATIC_STORAGE_KIND ?? 'local',
|
kind: process.env.KEYSTATIC_STORAGE_KIND ?? 'local',
|
||||||
@@ -34,6 +43,34 @@ const keyStaticConfig = createKeyStaticConfig();
|
|||||||
|
|
||||||
export default keyStaticConfig;
|
export default keyStaticConfig;
|
||||||
|
|
||||||
|
function getContentField() {
|
||||||
|
return fields.markdoc({
|
||||||
|
label: 'Content',
|
||||||
|
options: {
|
||||||
|
link: true,
|
||||||
|
blockquote: true,
|
||||||
|
bold: true,
|
||||||
|
divider: true,
|
||||||
|
orderedList: true,
|
||||||
|
unorderedList: true,
|
||||||
|
strikethrough: true,
|
||||||
|
heading: true,
|
||||||
|
code: true,
|
||||||
|
italic: true,
|
||||||
|
image: {
|
||||||
|
directory: 'public/site/images',
|
||||||
|
publicPath: '/site/images',
|
||||||
|
schema: {
|
||||||
|
title: fields.text({
|
||||||
|
label: 'Caption',
|
||||||
|
description: 'The text to display under the image in a caption.',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export type PostEntryProps = Entry<
|
export type PostEntryProps = Entry<
|
||||||
(typeof keyStaticConfig)['collections']['posts']
|
(typeof keyStaticConfig)['collections']['posts']
|
||||||
>;
|
>;
|
||||||
@@ -64,23 +101,7 @@ function createKeyStaticConfig() {
|
|||||||
}),
|
}),
|
||||||
language: fields.text({ label: 'Language' }),
|
language: fields.text({ label: 'Language' }),
|
||||||
order: fields.number({ label: 'Order' }),
|
order: fields.number({ label: 'Order' }),
|
||||||
content: fields.document({
|
content: getContentField(),
|
||||||
label: 'Content',
|
|
||||||
formatting: true,
|
|
||||||
dividers: true,
|
|
||||||
links: true,
|
|
||||||
images: {
|
|
||||||
directory: 'public/site/images',
|
|
||||||
publicPath: '/site/images',
|
|
||||||
schema: {
|
|
||||||
title: fields.text({
|
|
||||||
label: 'Caption',
|
|
||||||
description:
|
|
||||||
'The text to display under the image in a caption.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
documentation: collection({
|
documentation: collection({
|
||||||
@@ -90,23 +111,7 @@ function createKeyStaticConfig() {
|
|||||||
format: { contentField: 'content' },
|
format: { contentField: 'content' },
|
||||||
schema: {
|
schema: {
|
||||||
title: fields.slug({ name: { label: 'Title' } }),
|
title: fields.slug({ name: { label: 'Title' } }),
|
||||||
content: fields.document({
|
content: getContentField(),
|
||||||
label: 'Content',
|
|
||||||
formatting: true,
|
|
||||||
dividers: true,
|
|
||||||
links: true,
|
|
||||||
images: {
|
|
||||||
directory: 'public/site/images',
|
|
||||||
publicPath: '/site/images',
|
|
||||||
schema: {
|
|
||||||
title: fields.text({
|
|
||||||
label: 'Caption',
|
|
||||||
description:
|
|
||||||
'The text to display under the image in a caption.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
image: fields.image({
|
image: fields.image({
|
||||||
label: 'Image',
|
label: 'Image',
|
||||||
directory: 'public/site/images',
|
directory: 'public/site/images',
|
||||||
|
|||||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@@ -426,6 +426,9 @@ importers:
|
|||||||
'@keystatic/next':
|
'@keystatic/next':
|
||||||
specifier: 5.0.0
|
specifier: 5.0.0
|
||||||
version: 5.0.0(@keystatic/core@0.5.14)(next@14.2.3)(react-dom@18.3.1)(react@18.3.1)
|
version: 5.0.0(@keystatic/core@0.5.14)(next@14.2.3)(react-dom@18.3.1)(react@18.3.1)
|
||||||
|
'@markdoc/markdoc':
|
||||||
|
specifier: ^0.4.0
|
||||||
|
version: 0.4.0(@types/react@18.3.1)(react@18.3.1)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@kit/cms':
|
'@kit/cms':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@@ -445,6 +448,12 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20.12.8
|
specifier: ^20.12.8
|
||||||
version: 20.12.10
|
version: 20.12.10
|
||||||
|
'@types/react':
|
||||||
|
specifier: ^18.3.1
|
||||||
|
version: 18.3.1
|
||||||
|
react:
|
||||||
|
specifier: 18.3.1
|
||||||
|
version: 18.3.1
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.23.6
|
specifier: ^3.23.6
|
||||||
version: 3.23.6
|
version: 3.23.6
|
||||||
|
|||||||
Reference in New Issue
Block a user