158 lines
4.5 KiB
TypeScript
158 lines
4.5 KiB
TypeScript
import { defineDocumentType, ComputedFields, makeSource } from 'contentlayer/source-files'
|
|
import { writeFileSync } from 'fs'
|
|
import readingTime from 'reading-time'
|
|
import GithubSlugger from 'github-slugger'
|
|
import path from 'path'
|
|
// Remark packages
|
|
import remarkGfm from 'remark-gfm'
|
|
import remarkMath from 'remark-math'
|
|
import {
|
|
remarkExtractFrontmatter,
|
|
remarkCodeTitles,
|
|
remarkImgToJsx,
|
|
extractTocHeadings,
|
|
} from 'pliny/mdx-plugins/index.js'
|
|
// Rehype packages
|
|
import rehypeSlug from 'rehype-slug'
|
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
|
import rehypeKatex from 'rehype-katex'
|
|
import rehypeCitation from 'rehype-citation'
|
|
import rehypePrismPlus from 'rehype-prism-plus'
|
|
import rehypePresetMinify from 'rehype-preset-minify'
|
|
import siteMetadata from './data/siteMetadata'
|
|
import { allCoreContent, sortPosts } from 'pliny/utils/contentlayer.js'
|
|
|
|
const root = process.cwd()
|
|
|
|
const computedFields: ComputedFields = {
|
|
readingTime: { type: 'json', resolve: (doc) => readingTime(doc.body.raw) },
|
|
slug: {
|
|
type: 'string',
|
|
resolve: (doc) => doc._raw.flattenedPath.replace(/^.+?(\/)/, ''),
|
|
},
|
|
path: {
|
|
type: 'string',
|
|
resolve: (doc) => doc._raw.flattenedPath,
|
|
},
|
|
filePath: {
|
|
type: 'string',
|
|
resolve: (doc) => doc._raw.sourceFilePath,
|
|
},
|
|
toc: { type: 'string', resolve: (doc) => extractTocHeadings(doc.body.raw) },
|
|
}
|
|
|
|
/**
|
|
* Count the occurrences of all tags across blog posts and write to json file
|
|
*/
|
|
function createTagCount(allBlogs) {
|
|
const tagCount: Record<string, number> = {}
|
|
allBlogs.forEach((file) => {
|
|
if (file.tags && file.draft !== true) {
|
|
file.tags.forEach((tag) => {
|
|
const formattedTag = GithubSlugger.slug(tag)
|
|
if (formattedTag in tagCount) {
|
|
tagCount[formattedTag] += 1
|
|
} else {
|
|
tagCount[formattedTag] = 1
|
|
}
|
|
})
|
|
}
|
|
})
|
|
writeFileSync('./app/tag-data.json', JSON.stringify(tagCount))
|
|
}
|
|
|
|
function createSearchIndex(allBlogs) {
|
|
if (
|
|
siteMetadata?.search?.provider === 'kbar' &&
|
|
siteMetadata.search.kbarConfig.searchDocumentsPath
|
|
) {
|
|
writeFileSync(
|
|
`public/${siteMetadata.search.kbarConfig.searchDocumentsPath}`,
|
|
JSON.stringify(allCoreContent(sortPosts(allBlogs)))
|
|
)
|
|
console.log('Local search index generated...')
|
|
}
|
|
}
|
|
|
|
export const Blog = defineDocumentType(() => ({
|
|
name: 'Blog',
|
|
filePathPattern: 'blog/**/*.mdx',
|
|
contentType: 'mdx',
|
|
fields: {
|
|
title: { type: 'string', required: true },
|
|
date: { type: 'date', required: true },
|
|
tags: { type: 'list', of: { type: 'string' }, default: [] },
|
|
lastmod: { type: 'date' },
|
|
draft: { type: 'boolean' },
|
|
summary: { type: 'string' },
|
|
images: { type: 'list', of: { type: 'string' } },
|
|
authors: { type: 'list', of: { type: 'string' } },
|
|
layout: { type: 'string' },
|
|
bibliography: { type: 'string' },
|
|
canonicalUrl: { type: 'string' },
|
|
},
|
|
computedFields: {
|
|
...computedFields,
|
|
structuredData: {
|
|
type: 'json',
|
|
resolve: (doc) => ({
|
|
'@context': 'https://schema.org',
|
|
'@type': 'BlogPosting',
|
|
headline: doc.title,
|
|
datePublished: doc.date,
|
|
dateModified: doc.lastmod || doc.date,
|
|
description: doc.summary,
|
|
image: doc.images ? doc.images[0] : siteMetadata.socialBanner,
|
|
url: `${siteMetadata.siteUrl}/${doc._raw.flattenedPath}`,
|
|
author: doc.authors,
|
|
}),
|
|
},
|
|
},
|
|
}))
|
|
|
|
export const Authors = defineDocumentType(() => ({
|
|
name: 'Authors',
|
|
filePathPattern: 'authors/**/*.mdx',
|
|
contentType: 'mdx',
|
|
fields: {
|
|
name: { type: 'string', required: true },
|
|
avatar: { type: 'string' },
|
|
occupation: { type: 'string' },
|
|
company: { type: 'string' },
|
|
email: { type: 'string' },
|
|
twitter: { type: 'string' },
|
|
linkedin: { type: 'string' },
|
|
github: { type: 'string' },
|
|
layout: { type: 'string' },
|
|
},
|
|
computedFields,
|
|
}))
|
|
|
|
export default makeSource({
|
|
contentDirPath: 'data',
|
|
documentTypes: [Blog, Authors],
|
|
mdx: {
|
|
cwd: process.cwd(),
|
|
remarkPlugins: [
|
|
remarkExtractFrontmatter,
|
|
remarkGfm,
|
|
remarkCodeTitles,
|
|
remarkMath,
|
|
remarkImgToJsx,
|
|
],
|
|
rehypePlugins: [
|
|
rehypeSlug,
|
|
rehypeAutolinkHeadings,
|
|
rehypeKatex,
|
|
[rehypeCitation, { path: path.join(root, 'data') }],
|
|
[rehypePrismPlus, { defaultLanguage: 'js', ignoreMissing: true }],
|
|
rehypePresetMinify,
|
|
],
|
|
},
|
|
onSuccess: async (importData) => {
|
|
const { allBlogs } = await importData()
|
|
createTagCount(allBlogs)
|
|
createSearchIndex(allBlogs)
|
|
},
|
|
})
|