Add book, engineering, and writing content handling with MDX support

This commit is contained in:
2026-02-01 19:40:55 +03:00
parent 634281b3f4
commit 72f7063314
4 changed files with 134 additions and 13 deletions
+40
View File
@@ -0,0 +1,40 @@
import { getMdxContent, MaybeContent } from "./mdx";
import path from "path";
import fs from "fs";
export interface Book {
title: string;
author: string;
date: string;
rating: number;
coverImage: string;
spineColor: string;
textColor: string;
slug: string;
summary: string;
}
export function getAllBooks(): Book[] {
return JSON.parse(
fs.readFileSync(
path.join(process.cwd(), "content", "books", "index.json"),
"utf8",
),
);
}
export function getAllSlugs(): string[] {
const data = getAllBooks();
return data.map((item) => item.slug);
}
export async function getBook(slug: string): Promise<MaybeContent<Book>> {
const book = await getMdxContent<Book>("books", `${slug}.mdx`);
if (!book) {
return undefined;
}
return {
...book,
};
}
+32
View File
@@ -0,0 +1,32 @@
import path from "path";
import fs from "fs";
import { getMdxContent, MaybeContent } from "./mdx";
export interface Build {
title: string;
description: string;
image: string;
date: string;
url: string;
external: boolean;
source: string;
}
export function getAllBuildData(): Build[] {
return JSON.parse(
fs.readFileSync(
path.join(process.cwd(), "content", "engineering", "index.json"),
"utf8",
),
);
}
export function getAllSlugs(): string[] {
const data = getAllBuildData();
return data.filter((item) => !item.external).map((item) => item.url);
}
export async function getBuil(slug: string): Promise<MaybeContent<Build>> {
return getMdxContent<Build>("engineering", `${slug}.mdx`);
}
+11 -13
View File
@@ -5,7 +5,7 @@ import remarkGfm from "remark-gfm";
export interface Content<TMetadata = { [key: string]: any }> {
metadata: TMetadata;
content: string;
source: string;
}
export type MaybeContent<TMetadata> = Content<TMetadata> | undefined;
@@ -14,29 +14,27 @@ export async function getMdxContent<TMetadata>(
...paths: string[]
): Promise<MaybeContent<TMetadata>> {
const contentPath = path.join(process.cwd(), "content", ...paths);
if (!fs.existsSync(contentPath)) {
return undefined;
}
const content = fs.readFileSync(contentPath, "utf-8");
const content = fs.readFileSync(contentPath, "utf8");
const source = await serialize(content, {
parseFrontmatter: true,
mdxOptions: {
remarkPlugins: [remarkGfm],
development: false,
remarkPlugins: [remarkGfm],
},
});
// Remove the ugly footnotes heading from react-gfm
const footnotes =
/_jsx\(_components.h2, {.*?children: "Footnotes".*?}\), "\\n", /gs;
const hr = ``;
const compiledSource = source.compiledSource.replaceAll(footnotes, hr);
const footnotes = /_jsx\(_components.h2, {.*?children: "Footnotes".*?}\), "\\n", /gs;
const hr = ``
const compiledSource = source.compiledSource.replace(footnotes, hr);
return{
return {
metadata: source.frontmatter as TMetadata,
content: compiledSource,
}
source: compiledSource,
};
}
+51
View File
@@ -0,0 +1,51 @@
import path from "path";
import fs from "fs";
import { getMdxContent, MaybeContent } from "./mdx";
export interface DeepDive {
title: string;
image: string;
description: string;
links: {
label: string;
href: string;
}[];
}
export function getDeepDives(): DeepDive[] {
return JSON.parse(
fs.readFileSync(
path.join(process.cwd(), "content", "deep-dives", "index.json"),
"utf8"
)
);
}
export interface Post {
title: string;
description: string;
image: string;
date: string;
url: string;
external: boolean;
source: string;
}
export function getAllPostData(): Post[] {
return JSON.parse(
fs.readFileSync(
path.join(process.cwd(), "content", "writing", "index.json"),
"utf8"
)
);
}
export function getAllSlugs(): string[] {
const data = getAllPostData();
return data.filter((item) => !item.external).map((item) => item.url);
}
export async function getPost(slug: string): Promise<MaybeContent<Post>> {
return getMdxContent<Post>("writing", `${slug}.mdx`);
}