Files
pse.dev/lib/blog.ts
Kalidou Diagne f00649cb16 feat: blog section (#317)
* feat: blog section
2025-04-14 10:13:49 +02:00

96 lines
2.6 KiB
TypeScript

import fs from "fs"
import path from "path"
import matter from "gray-matter"
import jsYaml from "js-yaml"
export interface Article {
id: string
title: string
image?: string
tldr?: string
content: string
date: string
authors?: string[]
signature?: string
publicKey?: string
hash?: string
canonical?: string
}
const articlesDirectory = path.join(process.cwd(), "articles")
// Get all articles from /articles
export function getArticles(limit: number = 1000) {
// Get file names under /articles
const fileNames = fs.readdirSync(articlesDirectory)
const allArticlesData = fileNames.map((fileName: string) => {
const id = fileName.replace(/\.md$/, "")
if (id.toLowerCase() === "readme") {
return null
}
// Read markdown file as string
const fullPath = path.join(articlesDirectory, fileName)
const fileContents = fs.readFileSync(fullPath, "utf8")
try {
// Use matter with options to handle multiline strings
const matterResult = matter(fileContents, {
engines: {
yaml: {
// Ensure multiline strings are parsed correctly
parse: (str: string) => {
try {
// Use js-yaml's safe load to parse the YAML with type assertion
return jsYaml.load(str) as object
} catch (e) {
console.error(`Error parsing frontmatter in ${fileName}:`, e)
// Fallback to empty object if parsing fails
return {}
}
},
},
},
})
return {
id,
...matterResult.data,
content: matterResult.content,
}
} catch (error) {
console.error(`Error processing ${fileName}:`, error)
// Return minimal article data if there's an error
return {
id,
title: `Error processing ${id}`,
content: "This article could not be processed due to an error.",
date: new Date().toISOString().split("T")[0],
}
}
})
// Sort posts by date
return allArticlesData
.filter(Boolean)
.sort((a: any, b: any) => {
const dateA = new Date(a.date)
const dateB = new Date(b.date)
// Sort in descending order (newest first)
return dateB.getTime() - dateA.getTime()
})
.slice(0, limit)
.filter((article: any) => article.id !== "_article-template") as Article[]
}
export function getArticleById(slug?: string) {
const articles = getArticles()
return articles.find((article) => article.id === slug)
}
const lib = { getArticles, getArticleById }
export default lib