feat: add metadata display to blog posts

This commit is contained in:
Youwen Wu 2024-04-05 04:27:46 -07:00
parent 13069c4e2a
commit bd53c89296
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
4 changed files with 61 additions and 2 deletions

View file

@ -50,6 +50,7 @@
"@sveltejs/adapter-vercel": "^5.2.0", "@sveltejs/adapter-vercel": "^5.2.0",
"bits-ui": "^0.21.2", "bits-ui": "^0.21.2",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"dayjs": "^1.11.10",
"marked": "^12.0.1", "marked": "^12.0.1",
"marked-alert": "^2.0.1", "marked-alert": "^2.0.1",
"marked-katex-extension": "^5.0.1", "marked-katex-extension": "^5.0.1",

View file

@ -26,6 +26,9 @@ dependencies:
clsx: clsx:
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0 version: 2.1.0
dayjs:
specifier: ^1.11.10
version: 1.11.10
marked: marked:
specifier: ^12.0.1 specifier: ^12.0.1
version: 12.0.1 version: 12.0.1
@ -1453,6 +1456,10 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
/dayjs@1.11.10:
resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
dev: false
/debug@4.3.4: /debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}

View file

@ -2,6 +2,8 @@
import * as Card from '$lib/components/ui/card'; import * as Card from '$lib/components/ui/card';
import Placeholder from '$lib/assets/img/galaxy.jpg'; import Placeholder from '$lib/assets/img/galaxy.jpg';
import Button from '../ui/button/button.svelte'; import Button from '../ui/button/button.svelte';
import PostMetadata from './PostMetadata.svelte';
import { faker } from '@faker-js/faker';
export let title: string; export let title: string;
export let blurb: string; export let blurb: string;
@ -10,8 +12,14 @@
<Card.Root> <Card.Root>
<Card.Header> <Card.Header>
<h3 class="text-4xl font-serif font-bold mb-4">{title}</h3> <h3 class="text-4xl font-serif font-bold mb-4 leading-tight">{title}</h3>
<p class="text-muted-foreground text-xl">{blurb}</p> <p class="text-muted-foreground text-xl">{blurb}</p>
<PostMetadata
primaryTags={Array.from({ length: 3 }, () => faker.hacker.noun())}
secondaryTags={Array.from({ length: 2 }, () => faker.hacker.noun())}
time={Date.now() / 1000}
length={faker.number.int(1000)}
/>
</Card.Header> </Card.Header>
<Card.Content class="grid grid-cols-3 gap-6"> <Card.Content class="grid grid-cols-3 gap-6">
<img <img
@ -20,7 +28,7 @@
class="col-span-3 md:col-span-1 rounded-2xl shadow-md" class="col-span-3 md:col-span-1 rounded-2xl shadow-md"
/> />
<div class="flex flex-col justify-around col-span-3 md:col-span-2 gap-4"> <div class="flex flex-col justify-around col-span-3 md:col-span-2 gap-4">
<p class="text-primary/95 font-serif">{description}</p> <p class="text-primary/95 font-serif leading-relaxed">{description}</p>
<Button variant="outline" href="/blog/2024/test-post" class="text-xl flex-grow sm:flex-grow-0" <Button variant="outline" href="/blog/2024/test-post" class="text-xl flex-grow sm:flex-grow-0"
>Read More</Button >Read More</Button
> >

View file

@ -0,0 +1,43 @@
<!--
@component
This component is used to display the metadata of a blog post. It displays the primary and secondary tags, the time the post was published, and the estimated time it takes to read the post.
@props
- `primaryTags` - An array of strings representing the primary tags of the post.
- `secondaryTags` - An array of strings representing the secondary tags of the post.
- `time` - A unix epoch integer representing the time the post was published.
- `length` - An integer representing amount of words in the post.
-->
<script lang="ts">
import Badge from '../ui/badge/badge.svelte';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);
export let primaryTags: string[] = [];
export let secondaryTags: string[] = [];
export let time: number;
export let length: number;
let date = dayjs(time * 1000);
</script>
<div class="grid grid-cols-1">
<p class="text-muted-foreground/80 my-1 text-lg">{date.format('MM/DD/YY')}</p>
<span class="flex items-center flex-wrap my-2 gap-2">
{#each primaryTags as tag}
<Badge>{tag}</Badge>
{/each}
{#each secondaryTags as tag}
<Badge variant="secondary">{tag}</Badge>
{/each}
</span>
<!-- Assuming adult silent reading rate of 238 wpm -->
<span class="text-muted-foreground text-sm mt-2">
{dayjs(date).fromNow()} | {Math.round(length / 238)} min read | {length} words
</span>
</div>