From 72f7063314b3345e4ee299db9d5d6bb891e8f1fe Mon Sep 17 00:00:00 2001 From: andwati Date: Sun, 1 Feb 2026 19:40:55 +0300 Subject: [PATCH] Add book, engineering, and writing content handling with MDX support --- lib/book.ts | 40 ++++++++++++++++++++++++++++++++++++ lib/engineering.ts | 32 +++++++++++++++++++++++++++++ lib/mdx.ts | 24 ++++++++++------------ lib/writing.ts | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 lib/engineering.ts create mode 100644 lib/writing.ts diff --git a/lib/book.ts b/lib/book.ts index e69de29..601e96d 100644 --- a/lib/book.ts +++ b/lib/book.ts @@ -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> { + const book = await getMdxContent("books", `${slug}.mdx`); + if (!book) { + return undefined; + } + + return { + ...book, + }; +} diff --git a/lib/engineering.ts b/lib/engineering.ts new file mode 100644 index 0000000..6f232eb --- /dev/null +++ b/lib/engineering.ts @@ -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> { + return getMdxContent("engineering", `${slug}.mdx`); +} diff --git a/lib/mdx.ts b/lib/mdx.ts index 0ed0071..2a67ed7 100644 --- a/lib/mdx.ts +++ b/lib/mdx.ts @@ -5,7 +5,7 @@ import remarkGfm from "remark-gfm"; export interface Content { metadata: TMetadata; - content: string; + source: string; } export type MaybeContent = Content | undefined; @@ -14,29 +14,27 @@ export async function getMdxContent( ...paths: string[] ): Promise> { 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, + }; } diff --git a/lib/writing.ts b/lib/writing.ts new file mode 100644 index 0000000..9fb6501 --- /dev/null +++ b/lib/writing.ts @@ -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> { + return getMdxContent("writing", `${slug}.mdx`); +}