import type {Document, MDX} from "contentlayer2/core"; import {slug} from "github-slugger"; export type MDXDocument = Document & {body: MDX}; export type MDXDocumentDate = MDXDocument & { date: string; }; export type MDXBlog = MDXDocumentDate & { tags?: string[]; draft?: boolean; }; export type MDXAuthor = MDXDocument & { name: string; }; export function dateSortDesc(a: string, b: string) { if (a > b) return -1; if (a < b) return 1; return 0; } export function sortedBlogPost(allBlogs: MDXDocumentDate[]) { return allBlogs.sort((a, b) => dateSortDesc(a.date, b.date)); } type ConvertUndefined = OrNull<{ [K in keyof T as undefined extends T[K] ? K : never]-?: T[K]; }>; type OrNull = {[K in keyof T]: Exclude | null}; type PickRequired = { [K in keyof T as undefined extends T[K] ? never : K]: T[K]; }; type ConvertPick = ConvertUndefined & PickRequired; /** * A typesafe omit helper function * @example pick(content, ['title', 'description']) * * @param {Obj} obj * @param {Keys[]} keys * @return {*} {ConvertPick<{ [K in Keys]: Obj[K] }>} */ export const pick = ( obj: Obj, keys: Keys[], ): ConvertPick<{[K in Keys]: Obj[K]}> => { return keys.reduce((acc, key) => { acc[key] = obj[key] ?? null; return acc; }, {} as any); }; /** * A typesafe omit helper function * @example omit(content, ['body', '_raw', '_id']) * * @param {Obj} obj * @param {Keys[]} keys * @return {*} {Omit} */ export const omit = (obj: Obj, keys: Keys[]): Omit => { const result = Object.assign({}, obj); keys.forEach((key) => { delete result[key]; }); return result; }; export type CoreContent = Omit; export function coreContent(content: T) { return omit(content, ["body", "_raw", "_id"]); } export function allCoreContent(contents: T[]) { return contents.map((c) => coreContent(c)).filter((c) => !("draft" in c && c.draft === true)); } export async function getAllTags(allBlogs: MDXBlog[]) { const tagCount: Record = {}; allBlogs.forEach((file) => { if (file.tags && file.draft !== true) { file.tags.forEach((tag) => { const formattedTag = slug(tag); if (formattedTag in tagCount) { tagCount[formattedTag] += 1; } else { tagCount[formattedTag] = 1; } }); } }); return tagCount; }