From 644e31d7887d88031974dd8760eda7ac44f322dc Mon Sep 17 00:00:00 2001 From: Ryota Ikezawa Date: Sun, 17 Mar 2024 18:28:22 +0000 Subject: [PATCH] :gear: Added additional information to the posts, except for footnotes --- app/[...slug]/page.tsx | 2 +- app/posts/[...slug]/page.tsx | 27 ++++++++++--- components/category-badge.tsx | 24 ++++++++++++ components/ui/badge.tsx | 36 +++++++++++++++++ content/posts/sample.mdx | 1 + content/posts/without-category-post.mdx | 9 +++++ contentlayer.config.js | 6 +++ package.json | 2 + pnpm-lock.yaml | 52 +++++++++++++++++++++++++ 9 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 components/category-badge.tsx create mode 100644 components/ui/badge.tsx create mode 100644 content/posts/without-category-post.mdx diff --git a/app/[...slug]/page.tsx b/app/[...slug]/page.tsx index 4043c2e..5491441 100644 --- a/app/[...slug]/page.tsx +++ b/app/[...slug]/page.tsx @@ -45,7 +45,7 @@ export async function generateStaticParams(): Promise { } export default async function PagePage({ params }: PageProps) { - const pagePublishedDate = '2024-03-17' + const pagePublishedDate = '2024-03-17'; const page = await getPageFromParams(params); if (!page) { diff --git a/app/posts/[...slug]/page.tsx b/app/posts/[...slug]/page.tsx index 3f05425..933334e 100644 --- a/app/posts/[...slug]/page.tsx +++ b/app/posts/[...slug]/page.tsx @@ -2,10 +2,12 @@ import '@/styles/codes/prism-dracula.css'; import { notFound } from 'next/navigation'; import { Metadata } from 'next'; import { ArticleJsonLd } from 'next-seo'; +import { ReaderIcon } from '@radix-ui/react-icons'; import { allPosts } from 'contentlayer/generated'; import { Mdx } from '@/components/mdx-components'; import { TableOfContents } from '@/components/table-of-contents'; import { cfg } from '@/utils/constants'; +import { CategoryBadge } from '@/components/category-badge'; interface PostProps { params: { @@ -79,12 +81,25 @@ export default async function PostPage({ params }: PostProps) { authorName={cfg.author} description={post?.description ?? ''} /> -

{post.title}

- {post.date && ( -

- {formatDate(post.date)} -

- )} +

{post.title}

+
+ {post.date && ( + + {formatDate(post.date)} + + )} + + + + {post.readingTime && ( +
+ {post.readingTime.text} + + {post.readingTime.text} + +
+ )} +

{ + return [str] + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(''); +}; + +export const CategoryBadge = ({ badgeString }: Props) => { + const bs = badgeString ? toPascalCase(badgeString) : 'Other'; + return {bs}; +}; diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx new file mode 100644 index 0000000..9c6c4d9 --- /dev/null +++ b/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '@/lib/utils'; + +const badgeVariants = cva( + 'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', + { + variants: { + variant: { + default: + 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80', + secondary: + 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', + destructive: + 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80', + outline: 'text-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ); +} + +export { Badge, badgeVariants }; diff --git a/content/posts/sample.mdx b/content/posts/sample.mdx index 0e0c16d..4522e27 100644 --- a/content/posts/sample.mdx +++ b/content/posts/sample.mdx @@ -1,6 +1,7 @@ --- title: Sample description: Sample post +category: lifestyle date: 2020-01-01 --- diff --git a/content/posts/without-category-post.mdx b/content/posts/without-category-post.mdx new file mode 100644 index 0000000..34bedbd --- /dev/null +++ b/content/posts/without-category-post.mdx @@ -0,0 +1,9 @@ +--- +title: Without category post +description: This post doesn't have a category. +date: 2024-03-17 +--- + +## As a premise + +This post doesn't have a category, so, please check it. diff --git a/contentlayer.config.js b/contentlayer.config.js index 8a415e5..5d6c13a 100644 --- a/contentlayer.config.js +++ b/contentlayer.config.js @@ -2,9 +2,11 @@ import { defineDocumentType, makeSource } from 'contentlayer/source-files'; import rehypeSlug from 'rehype-slug'; import rehypePrism from 'rehype-prism-plus'; import rehypeCodeTitles from 'rehype-code-titles'; +import readingTime from 'reading-time'; /** @type {import('contentlayer/source-files').ComputedFields} */ const computedFields = { + readingTime: { type: 'json', resolve: (doc) => readingTime(doc.body.raw) }, slug: { type: 'string', resolve: (doc) => `/${doc._raw.flattenedPath}`, @@ -47,6 +49,10 @@ export const Post = defineDocumentType(() => ({ type: 'date', required: true, }, + category: { + type: 'string', + required: false, + }, }, computedFields, })); diff --git a/package.json b/package.json index 5509a77..daf4919 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,11 @@ "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", + "reading-time": "^1.5.0", "rehype-code-titles": "^1.2.0", "rehype-prism-plus": "^2.0.0", "rehype-slug": "^6.0.0", + "remark-footnotes": "^4.0.1", "tailwind-merge": "^2.2.1", "tailwindcss": "3.3.2", "tailwindcss-animate": "^1.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc63d90..850cc23 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,9 @@ dependencies: react-dom: specifier: 18.2.0 version: 18.2.0(react@18.2.0) + reading-time: + specifier: ^1.5.0 + version: 1.5.0 rehype-code-titles: specifier: ^1.2.0 version: 1.2.0 @@ -83,6 +86,9 @@ dependencies: rehype-slug: specifier: ^6.0.0 version: 6.0.0 + remark-footnotes: + specifier: ^4.0.1 + version: 4.0.1 tailwind-merge: specifier: ^2.2.1 version: 2.2.1 @@ -4766,6 +4772,17 @@ packages: unist-util-visit: 4.1.2 dev: false + /mdast-util-footnote@1.1.1: + resolution: + { + integrity: sha512-Y8JiA5fZm0kCqvugmSfaSvaVU2trhAmhCYXJOgPKVfmDa8isqzb5Tf7uWvCq4s8I+dll09GZjboItwZFSsD4JQ==, + } + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-markdown: 1.5.0 + micromark-util-normalize-identifier: 1.1.0 + dev: false + /mdast-util-from-markdown@1.3.1: resolution: { @@ -4982,6 +4999,22 @@ packages: uvu: 0.5.6 dev: false + /micromark-extension-footnote@1.0.2: + resolution: + { + integrity: sha512-sD7t/hooONLnbPYgcQpBcTjh7mPEcD2R/jRS5DLYDNm0XbngbaJZ01F1aI3v6VXVMdAu3XtFKUecNRlXbgGk/Q==, + } + dependencies: + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-symbol: 1.1.0 + uvu: 0.5.6 + dev: false + /micromark-extension-frontmatter@1.1.1: resolution: { @@ -6171,6 +6204,13 @@ packages: picomatch: 2.3.1 dev: false + /reading-time@1.5.0: + resolution: + { + integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==, + } + dev: false + /reflect.getprototypeof@1.0.5: resolution: { @@ -6280,6 +6320,18 @@ packages: unified: 10.1.2 dev: false + /remark-footnotes@4.0.1: + resolution: + { + integrity: sha512-He6YzQFk/Wu2KgfjI80EyPXjt/G+WFaYfUH+xapqPQBdm3aTdEyzosXXv9a2FbTxGqgOfJ4q/TCB46v+wofRpQ==, + } + dependencies: + '@types/mdast': 3.0.15 + mdast-util-footnote: 1.1.1 + micromark-extension-footnote: 1.0.2 + unified: 10.1.2 + dev: false + /remark-frontmatter@4.0.1: resolution: {