diff --git a/app/[...path]/page.tsx b/app/[...path]/page.tsx index d3d4e2ca..c896ca81 100644 --- a/app/[...path]/page.tsx +++ b/app/[...path]/page.tsx @@ -2,7 +2,11 @@ import PostCard from "shared/post-card"; import PressReleaseListing from "shared/press-releases"; import { Author } from "shared/author"; import { BlogPost, PostMetadata, stripBlogPostBody } from "shared/post"; -import { siteData } from "shared/site-data"; +import { + getAllAuthors, + getAllBlogPosts, + getAllPressReleases, +} from "shared/site-data"; import { markdownToHTML } from "shared/utils"; import { Metadata } from "next"; @@ -16,9 +20,9 @@ type Props = { const Post = ({ params }: Props) => { const post = postForPath(params.path); - const author = siteData.authors.find((a) => a.id === post.authorId)!; - const authors = siteData.authors; - const otherPosts = siteData.posts + const authors = getAllAuthors(); + const author = authors.find((a) => a.id === post.authorId)!; + const otherPosts = getAllBlogPosts() .filter((p) => p.path !== post.path) .map(stripBlogPostBody) .slice(0, 3); @@ -90,12 +94,12 @@ const PostBody = ({ post, author }: { post: BlogPost; author: Author }) => { const postForPath = (path: string[]) => { const mergedPath = "/" + path.join("/"); - const allPosts = [...siteData.posts, ...siteData.pressReleases]; + const allPosts = [...getAllBlogPosts(), ...getAllPressReleases()]; return allPosts.find((post) => post.path === mergedPath)!; }; export async function generateStaticParams(): Promise { - const allPosts = [...siteData.posts, ...siteData.pressReleases]; + const allPosts = [...getAllBlogPosts(), ...getAllPressReleases()]; return allPosts.map((post) => ({ path: post.path.split("/").slice(1), })); diff --git a/app/page.tsx b/app/page.tsx index 1ca5c01a..be8d8309 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,12 +1,12 @@ import { PostMetadata } from "shared/post"; -import { siteData } from "shared/site-data"; +import { getAllAuthors, getAllBlogPosts } from "shared/site-data"; import PostCard from "shared/post-card"; import PressReleaseListing from "shared/press-releases"; import { Metadata } from "next"; const Home = () => { - const authors = siteData.authors; - const [firstPost, ...otherPosts] = siteData.posts; + const authors = getAllAuthors(); + const [firstPost, ...otherPosts] = getAllBlogPosts(); const authorOf = (post: PostMetadata) => authors.find((a) => a.id === post.authorId)!; return ( diff --git a/pages/api/articles.ts b/pages/api/articles.ts index 8aba32b1..d20088d5 100644 --- a/pages/api/articles.ts +++ b/pages/api/articles.ts @@ -1,6 +1,6 @@ -import type { NextApiRequest, NextApiResponse } from "next"; +import { NextApiRequest, NextApiResponse } from "next"; import { BlogPost } from "shared/post"; -import { siteData } from "shared/site-data"; +import { getAllBlogPosts } from "shared/site-data"; interface PublicParams { url: string; @@ -30,7 +30,7 @@ export default async function handler( request: NextApiRequest, response: NextApiResponse ) { - const posts = siteData.posts.map(getPublicParamsForPost); + const posts = getAllBlogPosts().map(getPublicParamsForPost); response.setHeader("Content-Type", "application/json"); response.status(200).send(JSON.stringify(posts, null, 2)); } diff --git a/pages/api/feed.ts b/pages/api/feed.ts index d67e3371..96ef8aa1 100644 --- a/pages/api/feed.ts +++ b/pages/api/feed.ts @@ -1,6 +1,6 @@ -import type { NextApiRequest, NextApiResponse } from "next"; +import { NextApiRequest, NextApiResponse } from "next"; import { Feed } from "feed"; -import { siteData } from "shared/site-data"; +import { getAllBlogPosts } from "shared/site-data"; import { feedItemFromBlogPost } from "shared/utils"; export default async function handler( @@ -16,7 +16,7 @@ export default async function handler( image: "https://data.cesko.digital/img/172a1526.png", copyright: "Česko.Digital a přispěvatelé", }); - siteData.posts.map(feedItemFromBlogPost).forEach(feed.addItem); + getAllBlogPosts().map(feedItemFromBlogPost).forEach(feed.addItem); response.setHeader( "Content-Type", request.query.plain ? "text/plain" : "application/rss+xml" diff --git a/shared/press-releases.tsx b/shared/press-releases.tsx index 9b7cc098..d540c50d 100644 --- a/shared/press-releases.tsx +++ b/shared/press-releases.tsx @@ -1,8 +1,8 @@ -import { siteData } from "shared/site-data"; +import { getAllPressReleases } from "shared/site-data"; import Link from "next/link"; const PressReleaseListing = () => { - const posts = siteData.pressReleases.slice(0, 6); + const posts = getAllPressReleases().slice(0, 6); const formatDate = (stamp: string) => new Date(stamp).toLocaleDateString("cs-CZ", { dateStyle: "medium" }); return ( diff --git a/shared/site-data.ts b/shared/site-data.ts index b6ac45a4..ec7855ed 100644 --- a/shared/site-data.ts +++ b/shared/site-data.ts @@ -1,29 +1,19 @@ -import { Author, getAllAuthors } from "./author"; -import { BlogPost, compareBlogPostsByDate } from "./post"; +import { getAllAuthors as getAllAuthorsFromFile } from "./author"; +import { compareBlogPostsByDate } from "./post"; import { getAllPosts } from "./post-loading"; import { join, resolve } from "path"; +import { cache } from "react"; -export interface SiteData { - posts: readonly BlogPost[]; - pressReleases: readonly BlogPost[]; - authors: readonly Author[]; -} +const contentRoot = resolve(process.cwd(), "content"); -function loadSiteData(): SiteData { - const content = resolve(process.cwd(), "content"); - console.log(`Loading data files from ${content}`); - const byDate = compareBlogPostsByDate; - const posts = getAllPosts(join(content, "posts")).sort(byDate); - const pressReleases = getAllPosts(join(content, "press")).sort(byDate); - const authors = getAllAuthors(join(content, "authors.yaml")); - console.log( - `Loaded ${posts.length} posts, ${pressReleases.length} press releases, ${authors.length} authors.` - ); - return { - posts, - pressReleases, - authors, - }; -} +export const getAllBlogPosts = cache(() => + getAllPosts(join(contentRoot, "posts")).sort(compareBlogPostsByDate) +); -export const siteData = loadSiteData(); +export const getAllPressReleases = cache(() => + getAllPosts(join(contentRoot, "press")).sort(compareBlogPostsByDate) +); + +export const getAllAuthors = cache(() => + getAllAuthorsFromFile(join(contentRoot, "authors.yaml")) +);