Files
lixiyu-net/lib/post-process.ts
2024-04-03 22:08:27 +08:00

106 lines
3.3 KiB
TypeScript

import { PostsRootDirectory } from "@/consts/consts";
import { TFrontmatter } from "@/types/frontmatter.type";
import { TPostListItem, TPostsByTag } from "@/types/post-list";
import fs from "fs";
import { serialize } from "next-mdx-remote/serialize";
import path from "path";
import { isEmptyString, nullifyEmptyArray, nullifyEmptyString } from "./utils";
async function extractFrontmatters(filepath: string): Promise<TFrontmatter> {
const source = fs.readFileSync(filepath, "utf-8");
const mdxSource = await serialize(source, {
parseFrontmatter: true,
mdxOptions: { format: "md" },
});
const frontmatter = mdxSource.frontmatter as TFrontmatter;
const normalizedTags = frontmatter.tags
?.filter((tagname) => !isEmptyString(tagname))
.map((tagname) => tagname.toUpperCase());
const normalizedResult: TFrontmatter = {
title: frontmatter.title,
subtitle: nullifyEmptyString(frontmatter.subtitle),
coverURL: nullifyEmptyString(frontmatter.coverURL),
tags: nullifyEmptyArray(normalizedTags),
summary: nullifyEmptyString(frontmatter.summary),
time: frontmatter.time,
pin: frontmatter.pin ?? false,
noPrompt: frontmatter.noPrompt ?? false,
allowShare: frontmatter.allowShare ?? true,
closed: frontmatter.closed ?? false,
};
return normalizedResult;
}
function readPostsDirectory(): string[] {
const result: string[] = [];
fs.readdirSync(PostsRootDirectory).forEach((fileName) => {
const filePath = path.join(PostsRootDirectory, fileName);
const fileStat = fs.statSync(filePath);
if (fileStat.isFile() && fileName.endsWith(".md")) {
result.push(filePath);
}
});
return result;
}
export const getPostFileContent = (postId: string): string | null => {
const filePath = path.join(PostsRootDirectory, `${postId}.md`);
if (!fs.existsSync(filePath)) return null;
const content = fs.readFileSync(filePath, "utf-8");
return content;
};
const sortOutPosts = async (): Promise<{
allPostList: TPostListItem[];
pinnedPostList: TPostListItem[];
postsByTag: TPostsByTag;
}> => {
const allPostList: TPostListItem[] = [];
const pinnedPostList: TPostListItem[] = [];
const postsByTag: TPostsByTag = {};
const postFilePaths: string[] = readPostsDirectory();
for (let i = 0; i < postFilePaths.length; i++) {
const frontmatter = await extractFrontmatters(postFilePaths[i]);
const postId = path.parse(postFilePaths[i]).name;
const currentPostListItem: TPostListItem = {
id: postId,
frontMatter: frontmatter,
};
if (!currentPostListItem.frontMatter.closed) {
allPostList.push(currentPostListItem);
if (currentPostListItem.frontMatter.pin) {
pinnedPostList.push(currentPostListItem);
}
}
}
pinnedPostList.sort((a, b) => {
return a.frontMatter.time > b.frontMatter.time ? -1 : 1;
});
allPostList.sort((a, b) => {
return a.frontMatter.time > b.frontMatter.time ? -1 : 1;
});
allPostList.forEach((item) => {
item.frontMatter.tags?.forEach((tagName) => {
if (postsByTag[tagName] == null) {
postsByTag[tagName] = [];
}
postsByTag[tagName].push(item);
});
});
return { allPostList: allPostList, postsByTag: postsByTag, pinnedPostList: pinnedPostList };
};
export const sortedPosts = await sortOutPosts();