Files
myeasycms-v2/packages/cms/contentlayer/contentlayer.config.js
giancarlo 6b72206b00 Refactor CMS to handle ContentLayer and WordPress platforms
This commit refactors the CMS to handle two platforms: ContentLayer and WordPress. The CMS layer is abstracted into a core package, and separate implementations for each platform are created. This change allows the app to switch the CMS type based on environment variable, which can improve the flexibility of content management. It also updates several functions in the `server-sitemap.xml` route to accommodate these changes and generate sitemaps based on the CMS client. Further, documentation content and posts have been relocated to align with the new structure. Notably, this refactor is a comprehensive update to the way the CMS is structured and managed.
2024-04-01 19:47:51 +08:00

238 lines
5.2 KiB
JavaScript

import { defineDocumentType, makeSource } from 'contentlayer/source-files';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';
export const Post = defineDocumentType(() => ({
name: 'Post',
filePathPattern: `posts/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
description: 'The title of the post',
required: true,
},
date: {
type: 'date',
description: 'The date of the post',
required: true,
},
author: {
type: 'string',
description: 'The author of the post',
required: true,
},
live: {
type: 'boolean',
description: 'Whether the post is live or not',
required: true,
default: false,
},
image: {
type: 'string',
description: 'The path to the cover image',
},
description: {
type: 'string',
description: 'The description of the post',
},
tags: {
type: 'list',
required: false,
of: {
type: 'string',
},
},
categories: {
type: 'list',
required: false,
of: {
type: 'string',
},
},
},
computedFields: {
readingTime: {
type: 'number',
resolve: (post) => calculateReadingTime(post.body.raw),
},
slug: {
type: 'string',
resolve: (post) => getSlug(post._raw.sourceFileName),
},
url: {
type: 'string',
resolve: (post) => `/blog/${getSlug(post._raw.sourceFileName)}`,
},
structuredData: {
type: 'object',
resolve: (doc) => ({
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: doc.title,
datePublished: doc.date,
dateModified: doc.date,
description: doc.description,
image: [siteUrl, doc.image].join(''),
author: {
'@type': 'Organization',
name: `Makerkit`,
},
}),
},
},
}));
export const DocumentationPage = defineDocumentType(() => ({
name: 'DocumentationPage',
filePathPattern: `docs/**/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
description: 'The title of the post',
required: true,
},
label: {
type: 'string',
description: 'The label of the page in the sidebar',
required: true,
},
description: {
type: 'string',
description: 'The description of the post',
},
tags: {
type: 'list',
required: false,
of: {
type: 'string',
},
},
categories: {
type: 'list',
required: false,
of: {
type: 'string',
},
},
},
computedFields: {
readingTime: {
type: 'number',
resolve: (post) => calculateReadingTime(post.body.raw),
},
structuredData: {
type: 'object',
resolve: (doc) => ({
'@context': 'https://schema.org',
'@type': 'LearningResource',
headline: doc.title,
datePublished: doc.date,
dateModified: doc.date,
description: doc.description,
image: [siteUrl, doc.image].join(''),
url: [siteUrl, 'blog', doc._raw.flattenedPath].join('/'),
author: {
'@type': 'Organization',
name: `Makerkit`,
},
}),
},
path: {
type: 'string',
resolve: (doc) => {
if (doc._id.startsWith('docs/index.md')) {
return '/docs';
}
return urlFromFilePath(doc);
},
},
pathSegments: {
type: 'json',
resolve: (doc) => getPathSegments(doc).map(getMetaFromFolderName),
},
slug: {
type: 'string',
resolve: (doc) =>
getPathSegments(doc)
.map(getMetaFromFolderName)
.map(({ pathName }) => pathName)
.join('/'),
},
url: {
type: 'string',
resolve: (doc) => {
return (
'/docs/' +
getPathSegments(doc)
.map(getMetaFromFolderName)
.map(({ pathName }) => pathName)
.join('/')
);
},
},
},
}));
export default makeSource({
contentDirPath: './content',
documentTypes: [Post, DocumentationPage],
mdx: {
remarkPlugins: [],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: {
className: ['anchor'],
},
},
],
],
},
});
function calculateReadingTime(content) {
const wordsPerMinute = 235;
const numberOfWords = content.split(/\s/g).length;
const minutes = numberOfWords / wordsPerMinute;
return Math.ceil(minutes);
}
function getSlug(fileName) {
return fileName.replace('.mdx', '');
}
function urlFromFilePath(doc) {
let urlPath = doc._raw.flattenedPath.replace(/^app\/?/, '/');
if (!urlPath.startsWith('/')) {
urlPath = `/${urlPath}`;
}
return urlPath;
}
function getMetaFromFolderName(dirName) {
const re = /^((\d+)-)?(.*)$/;
const [, , orderStr, pathName] = dirName.match(re) ?? [];
const order = orderStr ? parseInt(orderStr) : 0;
return { order, pathName };
}
function getPathSegments(doc) {
return (
urlFromFilePath(doc)
.split('/')
// skip `/docs` prefix
.slice(2)
);
}