upgrade the project
This commit is contained in:
@@ -2,8 +2,7 @@
|
||||
* Convert the date format of YYYY-MM-DD to American writing
|
||||
* @param date The date in format of YYYY-MM-DD.
|
||||
*/
|
||||
export const normalizeDate = (date: string): string => {
|
||||
if (date == null) return "01 January, 1970";
|
||||
export const normalizeDate = (date: string = "1970-01-01"): string => {
|
||||
let [year, month, day] = date.split("-");
|
||||
let month_num = parseInt(month);
|
||||
let day_num = parseInt(day);
|
||||
|
||||
@@ -1,91 +1,105 @@
|
||||
import { PostsRootDirectory } from "@/consts/consts";
|
||||
import { TFrontmatter } from "@/types/frontmatter.type";
|
||||
import { TPostListItem, TTagSubPostSet } from "@/types/post-list";
|
||||
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 getFrontmatters(filepath: string): Promise<TFrontmatter> {
|
||||
async function extractFrontmatters(filepath: string): Promise<TFrontmatter> {
|
||||
const source = fs.readFileSync(filepath, "utf-8");
|
||||
const mdxSource = await serialize(source, {
|
||||
parseFrontmatter: true,
|
||||
mdxOptions: { format: "md" },
|
||||
});
|
||||
return mdxSource.frontmatter as TFrontmatter;
|
||||
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;
|
||||
}
|
||||
|
||||
export const getPostFileContent = (postId: string): string | null => {
|
||||
const filePath = path.join(PostsRootDirectory, `${postId}.md`);
|
||||
if (!fs.existsSync(filePath)) return null;
|
||||
const source = fs.readFileSync(filePath, "utf-8");
|
||||
return source;
|
||||
};
|
||||
|
||||
const sortOutPostLists = async (): Promise<{
|
||||
allPostList: TPostListItem[];
|
||||
pinnedPostList: TPostListItem[];
|
||||
tagSubPostSet: TTagSubPostSet;
|
||||
}> => {
|
||||
const allPostListItems: TPostListItem[] = [];
|
||||
const pinnedPostList: TPostListItem[] = [];
|
||||
const tagSubPostSet: TTagSubPostSet = {};
|
||||
|
||||
const postFilePaths: string[] = [];
|
||||
|
||||
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")) {
|
||||
postFilePaths.push(filePath);
|
||||
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 getFrontmatters(postFilePaths[i]);
|
||||
const frontmatter = await extractFrontmatters(postFilePaths[i]);
|
||||
const postId = path.parse(postFilePaths[i]).name;
|
||||
|
||||
const normalizedTags = frontmatter.tags
|
||||
?.filter((tagname) => !isEmptyString(tagname))
|
||||
.map((tagname) => tagname.toUpperCase());
|
||||
|
||||
const postListItem: TPostListItem = {
|
||||
const currentPostListItem: TPostListItem = {
|
||||
id: postId,
|
||||
frontMatter: {
|
||||
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,
|
||||
},
|
||||
frontMatter: frontmatter,
|
||||
};
|
||||
|
||||
allPostListItems.push(postListItem);
|
||||
|
||||
if (postListItem.frontMatter.pin) {
|
||||
pinnedPostList.push(postListItem);
|
||||
if (!currentPostListItem.frontMatter.closed) {
|
||||
allPostList.push(currentPostListItem);
|
||||
if (currentPostListItem.frontMatter.pin) {
|
||||
pinnedPostList.push(currentPostListItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allPostListItems.sort((a, b) => {
|
||||
pinnedPostList.sort((a, b) => {
|
||||
return a.frontMatter.time > b.frontMatter.time ? -1 : 1;
|
||||
});
|
||||
|
||||
allPostListItems.map((item) => {
|
||||
item.frontMatter.tags?.map((tagName) => {
|
||||
if (tagSubPostSet[tagName] == null) {
|
||||
tagSubPostSet[tagName] = [];
|
||||
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] = [];
|
||||
}
|
||||
tagSubPostSet[tagName].push(item);
|
||||
postsByTag[tagName].push(item);
|
||||
});
|
||||
});
|
||||
|
||||
return { allPostList: allPostListItems, tagSubPostSet: tagSubPostSet, pinnedPostList: pinnedPostList };
|
||||
return { allPostList: allPostList, postsByTag: postsByTag, pinnedPostList: pinnedPostList };
|
||||
};
|
||||
|
||||
export const sortedPosts = await sortOutPostLists();
|
||||
export const sortedPosts = await sortOutPosts();
|
||||
|
||||
@@ -57,11 +57,11 @@ export const generateRSSFeed = async () => {
|
||||
},
|
||||
});
|
||||
|
||||
for (let i = 0; i < LatestPostCountInHomePage; i++) {
|
||||
for (let i = 0; i < Math.min(LatestPostCountInHomePage, sortedPosts.allPostList.length); i++) {
|
||||
const post = sortedPosts.allPostList[i];
|
||||
const postContent = `${getPostFileContent(post.id)}${NoticeForRSSReaders}}`;
|
||||
const postFileContent = `${getPostFileContent(post.id)}${NoticeForRSSReaders}}`;
|
||||
const dateNumber = post.frontMatter.time.split("-").map((num) => parseInt(num));
|
||||
const mdxSource = await serialize(postContent ?? "", {
|
||||
const mdxSource = await serialize(postFileContent ?? "", {
|
||||
parseFrontmatter: true,
|
||||
mdxOptions: {
|
||||
remarkPlugins: [remarkPrism, externalLinks, remarkMath, remarkGfm],
|
||||
@@ -81,7 +81,7 @@ export const generateRSSFeed = async () => {
|
||||
{
|
||||
name: Config.AuthorName,
|
||||
email: Config.SocialLinks.email,
|
||||
link: `https://${Config.SiteDomain}/`,
|
||||
link: `https://${Config.SiteDomain}/about`,
|
||||
},
|
||||
],
|
||||
category: post.frontMatter.tags?.map((tagname) => ({ name: tagname })),
|
||||
|
||||
@@ -10,11 +10,12 @@ import { getPostFileContent, sortedPosts } from "./post-process";
|
||||
const CJKLRecognizeRegex = /[\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7A3a-zA-Z]+/g;
|
||||
|
||||
function tokenizer(str: string) {
|
||||
const result = cutForSearch(str, true).filter((item) => item.match(CJKLRecognizeRegex));
|
||||
const result = cutForSearch(str, true).filter((item) => CJKLRecognizeRegex.test(item));
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeSearchIndex() {
|
||||
const startTime = Date.now();
|
||||
let miniSearch = new minisearch({
|
||||
fields: ["id", "title", "tags", "subtitle", "summary", "content"],
|
||||
storeFields: ["id", "title", "tags"],
|
||||
@@ -32,8 +33,13 @@ function makeSearchIndex() {
|
||||
content: content,
|
||||
});
|
||||
}
|
||||
const endTime = Date.now();
|
||||
const sizeofIndex = (sizeof(miniSearch) / 1024 ** 2).toFixed(3);
|
||||
console.log(Colors.cyan(`Search index is ready. And the size of index is ${sizeofIndex} mb`));
|
||||
console.log(
|
||||
Colors.cyan(
|
||||
`Search index is ready. And the size of index is ${sizeofIndex} mb. And it costs ${(endTime - startTime) / 1000} s.`,
|
||||
),
|
||||
);
|
||||
return miniSearch;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { JSDOM } from "jsdom";
|
||||
* @param htmlCode
|
||||
* @returns
|
||||
*/
|
||||
export const getTOCTree = (htmlCode: string) => {
|
||||
export const makeTOCTree = (htmlCode: string) => {
|
||||
const doc_dom = new JSDOM(htmlCode);
|
||||
const all_headers = doc_dom.window.document.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
||||
const result: TTOCItem[] = [];
|
||||
|
||||
Reference in New Issue
Block a user