Leaflet Blog in Deno Fresh
1import { date } from "../lib/date.ts";
2import { env } from "../lib/env.ts";
3import { CgTimelapse } from "jsr:@preact-icons/cg";
4
5import { Paragraph } from "./typography.tsx";
6import type { ComponentChildren } from "preact";
7import { h } from "preact";
8
9// Wrapper component for the icon to handle compatibility issues
10const TimeIcon = () => h(CgTimelapse, { size: 13 });
11
12// Calculate reading time based on content length
13function getReadingTime(content: string): number {
14 const wordsPerMinute = 200;
15 const words = content.trim().split(/\s+/).length;
16 const minutes = Math.max(1, Math.ceil(words / wordsPerMinute));
17 return minutes;
18}
19
20export function PostInfo({
21 createdAt,
22 content,
23 includeAuthor = false,
24 className,
25 children,
26}: {
27 createdAt?: string;
28 content: string;
29 includeAuthor?: boolean;
30 className?: string;
31 children?: ComponentChildren;
32}) {
33 const readingTime = getReadingTime(content);
34
35 return (
36 <Paragraph className={className}>
37 {includeAuthor && (
38 <>
39 <a
40 href={`https://bsky.app/profile/${env.NEXT_PUBLIC_BSKY_DID}`}
41 className="hover:underline hover:underline-offset-4"
42 >
43 Roscoe Rubin-Rottenberg
44 </a>{" "}
45 ·{" "}
46 </>
47 )}
48 {createdAt && (
49 <>
50 <time dateTime={createdAt}>{date(new Date(createdAt))}</time>{" "}
51 ·{" "}
52 </>
53 )}
54 <span>
55 <span style={{ lineHeight: 1, marginRight: "0.25rem" }}>
56 {readingTime} min read
57 </span>
58 </span>
59 {children}
60 </Paragraph>
61 );
62}