From b99aae7ac9cd1d4ebb3861cee4100290a231df27 Mon Sep 17 00:00:00 2001 From: nemanjam Date: Sun, 16 Jun 2024 14:44:15 +0200 Subject: [PATCH] break modules/post.ts into separate files --- docs/my-old-code/open-graph/[...route].ts | 2 +- docs/todo3.md | 5 + src/components/CategoriesAndTags.astro | 6 +- src/components/CategoryCard.astro | 2 +- src/components/FilterList.astro | 2 +- src/components/PostCard.astro | 2 +- src/components/PostMeta.astro | 2 +- src/modules/feed.ts | 2 +- src/modules/post.ts | 241 ------------------ src/modules/post/category.ts | 53 ++++ src/modules/post/common.ts | 22 ++ src/modules/post/more.ts | 25 ++ src/modules/post/random.ts | 33 +++ src/modules/post/table-of-contents.ts | 38 +++ src/modules/post/tag.ts | 54 ++++ src/pages/api/open-graph/[...route].ts | 2 +- src/pages/blog/[...page].astro | 2 +- src/pages/blog/[slug].astro | 9 +- .../blog/categories-and-tags/index.astro | 2 +- .../categories/[category]/[...page].astro | 3 +- src/pages/blog/categories/index.astro | 5 +- src/pages/blog/tags/[tag]/[...page].astro | 3 +- src/pages/blog/tags/index.astro | 5 +- src/types/post.ts | 16 ++ 24 files changed, 271 insertions(+), 265 deletions(-) delete mode 100644 src/modules/post.ts create mode 100644 src/modules/post/category.ts create mode 100644 src/modules/post/common.ts create mode 100644 src/modules/post/more.ts create mode 100644 src/modules/post/random.ts create mode 100644 src/modules/post/table-of-contents.ts create mode 100644 src/modules/post/tag.ts diff --git a/docs/my-old-code/open-graph/[...route].ts b/docs/my-old-code/open-graph/[...route].ts index 2b0774a..9f25618 100644 --- a/docs/my-old-code/open-graph/[...route].ts +++ b/docs/my-old-code/open-graph/[...route].ts @@ -1,6 +1,6 @@ import { OGImageRoute } from 'astro-og-canvas'; -import { getAllPosts } from '@/modules/post'; +import { getAllPosts } from '@/modules/post/common'; import { getAllProjects } from '@/modules/project'; import { ROUTES } from '@/constants/routes'; diff --git a/docs/todo3.md b/docs/todo3.md index 1ee5bfc..ff6d9a4 100644 --- a/docs/todo3.md +++ b/docs/todo3.md @@ -310,4 +310,9 @@ fix image sizes for new PostCard link and primary single color put all components and variants in styleguide daisy ui color-mix() and oklch just to calc hover colors, i dont need it, hardcode it +sorted archive like in astro-cactus, route param highlight and link +refactor rss and json feed +ProjectCard and test markdown +PostCardSmall +extract types from constants ``` diff --git a/src/components/CategoriesAndTags.astro b/src/components/CategoriesAndTags.astro index deb4696..0ab56d7 100644 --- a/src/components/CategoriesAndTags.astro +++ b/src/components/CategoriesAndTags.astro @@ -1,14 +1,14 @@ --- import { Icon } from 'astro-icon/components'; -import { getCategoryLinks, getCategoryProps, getTagLinks } from '@/modules/post'; +import { getCategoryLinks, getCategoryProps } from '@/modules/post/category'; +import { getTagLinks } from '@/modules/post/tag'; import Button from '@/components/Button.astro'; import FilterList from '@/components/FilterList.astro'; import Tag from '@/components/Tag.astro'; import { cn } from '@/utils/styles'; -import type { FilterLink } from '@/modules/post'; -import type { PostCollection } from '@/types/post'; +import type { FilterLink, PostCollection } from '@/types/post'; export interface Props extends astroHTML.JSX.AnchorHTMLAttributes { posts: PostCollection[]; diff --git a/src/components/CategoryCard.astro b/src/components/CategoryCard.astro index 5a9437c..73aa29c 100644 --- a/src/components/CategoryCard.astro +++ b/src/components/CategoryCard.astro @@ -1,7 +1,7 @@ --- import { Icon } from 'astro-icon/components'; -import { getCategoryProps } from '@/modules/post'; +import { getCategoryProps } from '@/modules/post/category'; import { cn } from '@/utils/styles'; export interface Props extends astroHTML.JSX.AnchorHTMLAttributes { diff --git a/src/components/FilterList.astro b/src/components/FilterList.astro index 61e97df..b3962d1 100644 --- a/src/components/FilterList.astro +++ b/src/components/FilterList.astro @@ -1,7 +1,7 @@ --- import { cn } from '@/utils/styles'; -import type { FilterLink } from '@/modules/post'; +import type { FilterLink } from '@/types/post'; export interface Props extends astroHTML.JSX.AnchorHTMLAttributes { itemLinks: FilterLink[]; diff --git a/src/components/PostCard.astro b/src/components/PostCard.astro index 8b6eff7..b6753d1 100644 --- a/src/components/PostCard.astro +++ b/src/components/PostCard.astro @@ -2,7 +2,7 @@ import { Icon } from 'astro-icon/components'; import { Image } from 'astro:assets'; -import { getCategoryProps } from '@/modules/post'; +import { getCategoryProps } from '@/modules/post/category'; import Link from '@/components/Link.astro'; import { ROUTES } from '@/constants/routes'; import { formatDate, formatDateIso } from '@/utils/datetime'; diff --git a/src/components/PostMeta.astro b/src/components/PostMeta.astro index b8c874e..2ab73f3 100644 --- a/src/components/PostMeta.astro +++ b/src/components/PostMeta.astro @@ -5,7 +5,7 @@ import Link from '@/components/Link.astro'; import { ROUTES } from '@/constants/routes'; import { formatDate, formatDateIso } from '@/utils/datetime'; import { cn } from '@/utils/styles'; -import { getCategoryProps } from '@/modules/post'; +import { getCategoryProps } from '@/modules/post/category'; interface Props { publishDate: Date; diff --git a/src/modules/feed.ts b/src/modules/feed.ts index 9629ba5..74f8a73 100644 --- a/src/modules/feed.ts +++ b/src/modules/feed.ts @@ -2,7 +2,7 @@ import { createMarkdownProcessor } from '@astrojs/markdown-remark'; import { Feed } from 'feed'; -import { getAllPosts } from '@/modules/post'; +import { getAllPosts } from '@/modules/post/common'; import { ROUTES } from '@/constants/routes'; import { CONFIG } from '@/config'; diff --git a/src/modules/post.ts b/src/modules/post.ts deleted file mode 100644 index 075c421..0000000 --- a/src/modules/post.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { getAllEntries } from '@/modules/common'; -import { CATEGORIES, COLLECTIONS } from '@/constants/collections'; -import { ROUTES } from '@/constants/routes'; -import { CONFIG } from '@/config'; -import { renderMarkdown } from '@/utils/markdown'; - -import type { CategoryType } from '@/constants/collections'; -import type { Post, PostCollection } from '@/types/post'; -import type { MarkdownProcessorRenderResult } from '@astrojs/markdown-remark'; -import type { MarkdownHeading } from 'astro'; - -const { MORE_POSTS_COUNT } = CONFIG; - -/*-------------------------------- getAllPosts ------------------------------*/ - -export const getAllPosts = (): Promise => getAllEntries(COLLECTIONS.POST); - -export const getPostsWithReadingTimeFromPosts = async ( - posts: PostCollection[] -): Promise => { - const readingTimePromises = posts.map(async (post) => { - const { remarkPluginFrontmatter } = await post.render(); - const { readingTime } = remarkPluginFrontmatter; - return { readingTime }; - }); - const readingTimes = await Promise.all(readingTimePromises); - - // other frontmatter props are in post.data... - // readingTimes is in post.readingTimes - const postsWithReadingTime = posts.map((post, index) => ({ ...post, ...readingTimes[index] })); - return postsWithReadingTime; -}; - -/*-------------------------------- random Posts ------------------------------*/ - -export interface RandomPostsArgs { - posts: Post[]; - count?: number; - excludeSlug?: string; -} - -/** Must handle empty array. */ -export const getRandomPosts = ({ - posts, - count = MORE_POSTS_COUNT, - excludeSlug, -}: RandomPostsArgs): Post[] => { - if (!(posts.length > 0)) return []; - - const filteredPosts = posts.filter((post) => post.slug !== excludeSlug); - - if (!(filteredPosts.length > 0)) return []; - - const shuffledPosts = filteredPosts - .map((post) => ({ post, sort: Math.random() })) - .sort((a, b) => a.sort - b.sort) - .map(({ post }) => post); - - if (shuffledPosts.length < count) return shuffledPosts; - - return shuffledPosts.slice(0, count); -}; - -/*-------------------------------- Toc headings ------------------------------*/ - -export interface Heading extends Pick { - headings: Heading[]; -} - -export const getHeadingsForTableOfContents = (postHeadings: MarkdownHeading[]): Heading[] => { - // get subtitles for TOC - const headings: Heading[] = []; - - for (let index = 0; index < postHeadings.length; index++) { - const { slug, text, depth } = postHeadings[index]; - - if (depth !== 2) continue; - - // get subsequent depth 3 subheadings - // handle 2 - const subHeadings: Heading[] = []; - - // handle 3+ - while (index + 1 < postHeadings.length && postHeadings[index + 1].depth > 2) { - index++; - - // take only depth 3 - if (postHeadings[index].depth !== 3) continue; - - subHeadings.push({ - slug: postHeadings[index].slug, - text: postHeadings[index].text, - headings: [], - }); - } - - headings.push({ slug, text, headings: subHeadings }); - } - - return headings; -}; - -/*-------------------------------- More posts ------------------------------*/ - -// more posts with rendered md description -export type CollectionEntryWithRenderedDescription = PostCollection & { - renderedDescription: MarkdownProcessorRenderResult; -}; - -/** Don't use this, description without markdown, or myst wrap with prose. */ -export const getMorePostsWithRenderedMarkdownDescription = async ( - posts: PostCollection[] -): Promise => { - const morePosts: CollectionEntryWithRenderedDescription[] = []; - - for (const post of posts) { - const renderedDescription = await renderMarkdown(post.data.description ?? ''); - morePosts.push({ ...post, renderedDescription }); - } - - return morePosts; -}; - -/*-------------------------------- tags ------------------------------*/ - -export const getAllTags = (posts: PostCollection[]): string[] => { - const tags = posts.flatMap((post) => [...post.data.tags]); - return tags; -}; - -export const getUniqueTags = (posts: PostCollection[]): string[] => { - const uniqueTags = [...new Set([...getAllTags(posts)])]; - return uniqueTags; -}; - -export type FilterType = 'tag' | 'category'; - -/** For both tags and categories. */ -export interface Filter { - text: string; - count: number; -} - -export interface FilterLink { - href: string; - text: string; - count: number; - textWithCount: string; - isActive: boolean; -} - -export const getTagLinks = (posts: PostCollection[], pathname?: string): FilterLink[] => { - const filterItems = getSortedUniqueTagsWithCount(posts); - - const itemLinks = filterItems.map((item) => { - const { text, count } = item; - - const href = `${ROUTES.TAGS}${text}`; - const textWithCount = `#${text} ${count}`; - - // unused, wont display in category and tag list - const isActive = href === pathname; - - const link = { href, text, count, textWithCount, isActive }; - - return link; - }); - - return itemLinks; -}; - -export const getSortedUniqueTagsWithCount = (posts: PostCollection[]): Filter[] => { - // must have duplicated tags here to calc count - const tags = getAllTags(posts); - - if (!(tags.length > 0)) return []; - - const tagsWithCount = tags.reduce( - (acc, tag) => { - const index = acc.findIndex((item) => item.text === tag); - if (index === -1) return [...acc, { text: tag, count: 1 }]; - - acc[index].count++; - return acc; - }, - [] - ); - - const sortedTagsWithCount = tagsWithCount.slice().sort((a, b) => b.count - a.count); - return sortedTagsWithCount; -}; - -/*-------------------------------- categories ------------------------------*/ - -export const getAllCategories = (posts: PostCollection[]): string[] => - posts.map((post) => post.data.category).filter(Boolean) as string[]; - -export const getUniqueCategories = (posts: PostCollection[]): string[] => { - const uniqueCategories = [...new Set([...getAllCategories(posts)])]; - return uniqueCategories; -}; - -export const getSortedUniqueCategoriesWithCount = (posts: PostCollection[]): Filter[] => { - const categories = getAllCategories(posts); - if (!(categories.length > 0)) return []; - - const uniqueCategories = getUniqueCategories(posts); - - const categoriesWithCount = uniqueCategories.map((category) => { - const count = categories.filter((item) => item === category).length; - return { text: category, count }; - }); - - const sortedCategoriesWithCount = categoriesWithCount.slice().sort((a, b) => b.count - a.count); - return sortedCategoriesWithCount; -}; - -export const getCategoryLinks = (posts: PostCollection[], pathname?: string): FilterLink[] => { - const filterItems = getSortedUniqueCategoriesWithCount(posts); - - const itemLinks = filterItems.map((item) => { - const { text, count } = item; - - const href = `${ROUTES.CATEGORIES}${text}`; - const textWithCount = `${text} ${count}`; - - const isActive = href === pathname; - - const link = { href, text, count, textWithCount, isActive }; - - return link; - }); - - return itemLinks; -}; - -const defaultCategory = CATEGORIES[0]; - -/** set default to prevent breaking build */ -export const getCategoryProps = (categoryName: string): CategoryType => - CATEGORIES.find((item) => item.name === categoryName) ?? defaultCategory; diff --git a/src/modules/post/category.ts b/src/modules/post/category.ts new file mode 100644 index 0000000..eed5bd0 --- /dev/null +++ b/src/modules/post/category.ts @@ -0,0 +1,53 @@ +import { CATEGORIES } from '@/constants/collections'; +import { ROUTES } from '@/constants/routes'; + +import type { CategoryType } from '@/constants/collections'; +import type { Filter, FilterLink, PostCollection } from '@/types/post'; + +export const getAllCategories = (posts: PostCollection[]): string[] => + posts.map((post) => post.data.category).filter(Boolean) as string[]; + +export const getUniqueCategories = (posts: PostCollection[]): string[] => { + const uniqueCategories = [...new Set([...getAllCategories(posts)])]; + return uniqueCategories; +}; + +export const getSortedUniqueCategoriesWithCount = (posts: PostCollection[]): Filter[] => { + const categories = getAllCategories(posts); + if (!(categories.length > 0)) return []; + + const uniqueCategories = getUniqueCategories(posts); + + const categoriesWithCount = uniqueCategories.map((category) => { + const count = categories.filter((item) => item === category).length; + return { text: category, count }; + }); + + const sortedCategoriesWithCount = categoriesWithCount.slice().sort((a, b) => b.count - a.count); + return sortedCategoriesWithCount; +}; + +export const getCategoryLinks = (posts: PostCollection[], pathname?: string): FilterLink[] => { + const filterItems = getSortedUniqueCategoriesWithCount(posts); + + const itemLinks = filterItems.map((item) => { + const { text, count } = item; + + const href = `${ROUTES.CATEGORIES}${text}`; + const textWithCount = `${text} ${count}`; + + const isActive = href === pathname; + + const link = { href, text, count, textWithCount, isActive }; + + return link; + }); + + return itemLinks; +}; + +const defaultCategory = CATEGORIES[0]; + +/** set default to prevent breaking build */ +export const getCategoryProps = (categoryName: string): CategoryType => + CATEGORIES.find((item) => item.name === categoryName) ?? defaultCategory; diff --git a/src/modules/post/common.ts b/src/modules/post/common.ts new file mode 100644 index 0000000..a521a55 --- /dev/null +++ b/src/modules/post/common.ts @@ -0,0 +1,22 @@ +import { getAllEntries } from '@/modules/common'; +import { COLLECTIONS } from '@/constants/collections'; + +import type { Post, PostCollection } from '@/types/post'; + +export const getAllPosts = (): Promise => getAllEntries(COLLECTIONS.POST); + +export const getPostsWithReadingTimeFromPosts = async ( + posts: PostCollection[] +): Promise => { + const readingTimePromises = posts.map(async (post) => { + const { remarkPluginFrontmatter } = await post.render(); + const { readingTime } = remarkPluginFrontmatter; + return { readingTime }; + }); + const readingTimes = await Promise.all(readingTimePromises); + + // other frontmatter props are in post.data... + // readingTimes is in post.readingTimes + const postsWithReadingTime = posts.map((post, index) => ({ ...post, ...readingTimes[index] })); + return postsWithReadingTime; +}; diff --git a/src/modules/post/more.ts b/src/modules/post/more.ts new file mode 100644 index 0000000..1a6e2dd --- /dev/null +++ b/src/modules/post/more.ts @@ -0,0 +1,25 @@ +import { renderMarkdown } from '@/utils/markdown'; + +import type { PostCollection } from '@/types/post'; +import type { MarkdownProcessorRenderResult } from '@astrojs/markdown-remark'; + +// unused + +// more posts with rendered md description +export type CollectionEntryWithRenderedDescription = PostCollection & { + renderedDescription: MarkdownProcessorRenderResult; +}; + +/** Don't use this, description without markdown, or must wrap with prose. */ +export const getMorePostsWithRenderedMarkdownDescription = async ( + posts: PostCollection[] +): Promise => { + const morePosts: CollectionEntryWithRenderedDescription[] = []; + + for (const post of posts) { + const renderedDescription = await renderMarkdown(post.data.description ?? ''); + morePosts.push({ ...post, renderedDescription }); + } + + return morePosts; +}; diff --git a/src/modules/post/random.ts b/src/modules/post/random.ts new file mode 100644 index 0000000..e8738a1 --- /dev/null +++ b/src/modules/post/random.ts @@ -0,0 +1,33 @@ +import { CONFIG } from '@/config'; + +import type { Post } from '@/types/post'; + +const { MORE_POSTS_COUNT } = CONFIG; + +export interface RandomPostsArgs { + posts: Post[]; + count?: number; + excludeSlug?: string; +} + +/** Must handle empty array. */ +export const getRandomPosts = ({ + posts, + count = MORE_POSTS_COUNT, + excludeSlug, +}: RandomPostsArgs): Post[] => { + if (!(posts.length > 0)) return []; + + const filteredPosts = posts.filter((post) => post.slug !== excludeSlug); + + if (!(filteredPosts.length > 0)) return []; + + const shuffledPosts = filteredPosts + .map((post) => ({ post, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({ post }) => post); + + if (shuffledPosts.length < count) return shuffledPosts; + + return shuffledPosts.slice(0, count); +}; diff --git a/src/modules/post/table-of-contents.ts b/src/modules/post/table-of-contents.ts new file mode 100644 index 0000000..643b565 --- /dev/null +++ b/src/modules/post/table-of-contents.ts @@ -0,0 +1,38 @@ +import type { MarkdownHeading } from 'astro'; + +export interface Heading extends Pick { + headings: Heading[]; +} + +export const getHeadingsForTableOfContents = (postHeadings: MarkdownHeading[]): Heading[] => { + // get subtitles for TOC + const headings: Heading[] = []; + + for (let index = 0; index < postHeadings.length; index++) { + const { slug, text, depth } = postHeadings[index]; + + if (depth !== 2) continue; + + // get subsequent depth 3 subheadings + // handle 2 + const subHeadings: Heading[] = []; + + // handle 3+ + while (index + 1 < postHeadings.length && postHeadings[index + 1].depth > 2) { + index++; + + // take only depth 3 + if (postHeadings[index].depth !== 3) continue; + + subHeadings.push({ + slug: postHeadings[index].slug, + text: postHeadings[index].text, + headings: [], + }); + } + + headings.push({ slug, text, headings: subHeadings }); + } + + return headings; +}; diff --git a/src/modules/post/tag.ts b/src/modules/post/tag.ts new file mode 100644 index 0000000..a35e492 --- /dev/null +++ b/src/modules/post/tag.ts @@ -0,0 +1,54 @@ +import { ROUTES } from '@/constants/routes'; + +import type { Filter, FilterLink, PostCollection } from '@/types/post'; + +export const getAllTags = (posts: PostCollection[]): string[] => { + const tags = posts.flatMap((post) => [...post.data.tags]); + return tags; +}; + +export const getUniqueTags = (posts: PostCollection[]): string[] => { + const uniqueTags = [...new Set([...getAllTags(posts)])]; + return uniqueTags; +}; + +export const getTagLinks = (posts: PostCollection[], pathname?: string): FilterLink[] => { + const filterItems = getSortedUniqueTagsWithCount(posts); + + const itemLinks = filterItems.map((item) => { + const { text, count } = item; + + const href = `${ROUTES.TAGS}${text}`; + const textWithCount = `#${text} ${count}`; + + // unused, wont display in category and tag list + const isActive = href === pathname; + + const link = { href, text, count, textWithCount, isActive }; + + return link; + }); + + return itemLinks; +}; + +export const getSortedUniqueTagsWithCount = (posts: PostCollection[]): Filter[] => { + // must have duplicated tags here to calc count + const tags = getAllTags(posts); + + if (!(tags.length > 0)) return []; + + const tagsWithCount = tags.reduce( + (acc, tag) => { + const index = acc.findIndex((item) => item.text === tag); + if (index === -1) return [...acc, { text: tag, count: 1 }]; + + acc[index].count++; + return acc; + }, + [] + ); + + const sortedTagsWithCount = tagsWithCount.slice().sort((a, b) => b.count - a.count); + return sortedTagsWithCount; +}; diff --git a/src/pages/api/open-graph/[...route].ts b/src/pages/api/open-graph/[...route].ts index af957f8..e3f105e 100644 --- a/src/pages/api/open-graph/[...route].ts +++ b/src/pages/api/open-graph/[...route].ts @@ -1,6 +1,6 @@ import { OGImageRoute } from 'astro-og-canvas'; -import { getAllPosts } from '@/modules/post'; +import { getAllPosts } from '@/modules/post/common'; import { getAllProjects } from '@/modules/project'; import { DEFAULT_METADATA, OG_IMAGE_PREFIXES, PAGE_METADATA } from '@/constants/metadata'; diff --git a/src/pages/blog/[...page].astro b/src/pages/blog/[...page].astro index 8a4e738..fb80710 100644 --- a/src/pages/blog/[...page].astro +++ b/src/pages/blog/[...page].astro @@ -1,5 +1,5 @@ --- -import { getAllPosts, getPostsWithReadingTimeFromPosts } from '@/modules/post'; +import { getAllPosts, getPostsWithReadingTimeFromPosts } from '@/modules/post/common'; import List from '@/layouts/List.astro'; import PostList from '@/components/PostList.astro'; import { CONFIG } from '@/config'; diff --git a/src/pages/blog/[slug].astro b/src/pages/blog/[slug].astro index 60e1460..0c0af57 100644 --- a/src/pages/blog/[slug].astro +++ b/src/pages/blog/[slug].astro @@ -1,12 +1,9 @@ --- import { Image } from 'astro:assets'; -import { - getAllPosts, - getHeadingsForTableOfContents, - getPostsWithReadingTimeFromPosts, - getRandomPosts, -} from '@/modules/post'; +import { getAllPosts, getPostsWithReadingTimeFromPosts } from '@/modules/post/common'; +import { getRandomPosts } from '@/modules/post/random'; +import { getHeadingsForTableOfContents } from '@/modules/post/table-of-contents'; import { default as PostLayout } from '@/layouts/Post.astro'; import PostMeta from '@/components/PostMeta.astro'; import PostsListMore from '@/components/PostsListMore.astro'; diff --git a/src/pages/blog/categories-and-tags/index.astro b/src/pages/blog/categories-and-tags/index.astro index be285ff..4045543 100644 --- a/src/pages/blog/categories-and-tags/index.astro +++ b/src/pages/blog/categories-and-tags/index.astro @@ -1,5 +1,5 @@ --- -import { getAllPosts } from '@/modules/post'; +import { getAllPosts } from '@/modules/post/common'; import List from '@/layouts/List.astro'; import CategoriesAndTags from '@/components/CategoriesAndTags.astro'; import { getPageMetadata } from '@/utils/metadata'; diff --git a/src/pages/blog/categories/[category]/[...page].astro b/src/pages/blog/categories/[category]/[...page].astro index ea1e39e..2c5f6f0 100644 --- a/src/pages/blog/categories/[category]/[...page].astro +++ b/src/pages/blog/categories/[category]/[...page].astro @@ -1,5 +1,6 @@ --- -import { getAllPosts, getPostsWithReadingTimeFromPosts, getUniqueCategories } from '@/modules/post'; +import { getUniqueCategories } from '@/modules/post/category'; +import { getAllPosts, getPostsWithReadingTimeFromPosts } from '@/modules/post/common'; import List from '@/layouts/List.astro'; import Link from '@/components/Link.astro'; import PostList from '@/components/PostList.astro'; diff --git a/src/pages/blog/categories/index.astro b/src/pages/blog/categories/index.astro index 8fc6d28..721f7e8 100644 --- a/src/pages/blog/categories/index.astro +++ b/src/pages/blog/categories/index.astro @@ -1,11 +1,12 @@ --- -import { getAllPosts, getCategoryLinks } from '@/modules/post'; +import { getCategoryLinks } from '@/modules/post/category'; +import { getAllPosts } from '@/modules/post/common'; import List from '@/layouts/List.astro'; import CategoryCard from '@/components/CategoryCard.astro'; import FilterList from '@/components/FilterList.astro'; import { getPageMetadata } from '@/utils/metadata'; -import type { FilterLink } from '@/modules/post'; +import type { FilterLink } from '@/types/post'; const posts = await getAllPosts(); const categoryLinks = getCategoryLinks(posts); diff --git a/src/pages/blog/tags/[tag]/[...page].astro b/src/pages/blog/tags/[tag]/[...page].astro index 26bdcf7..761157f 100644 --- a/src/pages/blog/tags/[tag]/[...page].astro +++ b/src/pages/blog/tags/[tag]/[...page].astro @@ -1,5 +1,6 @@ --- -import { getAllPosts, getPostsWithReadingTimeFromPosts, getUniqueTags } from '@/modules/post'; +import { getAllPosts, getPostsWithReadingTimeFromPosts } from '@/modules/post/common'; +import { getUniqueTags } from '@/modules/post/tag'; import List from '@/layouts/List.astro'; import Link from '@/components/Link.astro'; import PostList from '@/components/PostList.astro'; diff --git a/src/pages/blog/tags/index.astro b/src/pages/blog/tags/index.astro index 6b09c0f..62ca1a2 100644 --- a/src/pages/blog/tags/index.astro +++ b/src/pages/blog/tags/index.astro @@ -1,12 +1,13 @@ --- -import { getAllPosts, getTagLinks } from '@/modules/post'; +import { getAllPosts } from '@/modules/post/common'; +import { getTagLinks } from '@/modules/post/tag'; import List from '@/layouts/List.astro'; import FilterList from '@/components/FilterList.astro'; import Tag from '@/components/Tag.astro'; import { getPageMetadata } from '@/utils/metadata'; import { cn } from '@/utils/styles'; -import type { FilterLink } from '@/modules/post'; +import type { FilterLink } from '@/types/post'; const allPosts = await getAllPosts(); diff --git a/src/types/post.ts b/src/types/post.ts index cb6566b..4457f92 100644 --- a/src/types/post.ts +++ b/src/types/post.ts @@ -7,3 +7,19 @@ export type PostCollection = CollectionEntry<'post'>; export type Post = PostCollection & { readingTime: number; }; + +export type FilterType = 'tag' | 'category'; + +/** For both tags and categories. */ +export interface Filter { + text: string; + count: number; +} + +export interface FilterLink { + href: string; + text: string; + count: number; + textWithCount: string; + isActive: boolean; +}