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 &middot;{" "} 46 </> 47 )} 48 {createdAt && ( 49 <> 50 <time dateTime={createdAt}>{date(new Date(createdAt))}</time>{" "} 51 &middot;{" "} 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}