at://Press
at main 50 lines 1.7 kB view raw
1export function formatDate(iso: string, opts?: { weekday?: boolean }): string { 2 const options: Intl.DateTimeFormatOptions = { 3 year: "numeric", 4 month: "long", 5 day: "numeric", 6 }; 7 if (opts?.weekday) options.weekday = "long"; 8 return new Date(iso).toLocaleDateString("en-US", options); 9} 10 11import { DEFAULT_EXCERPT_LENGTH } from "./constants"; 12 13export function excerpt(content: string, maxLen = DEFAULT_EXCERPT_LENGTH): string { 14 const plain = content 15 .replace(/^#{1,6}\s+/gm, "") 16 .replace(/\*{1,2}([^*]+)\*{1,2}/g, "$1") 17 .replace(/`([^`]+)`/g, "$1") 18 .replace(/~~~[\s\S]*?~~~/g, "") 19 .replace(/\n+/g, " ") 20 .trim(); 21 if (plain.length <= maxLen) return plain; 22 return plain.slice(0, maxLen).replace(/\s+\S*$/, "") + "\u2026"; 23} 24 25export function relativeTime(iso: string): string { 26 const seconds = Math.floor((Date.now() - new Date(iso).getTime()) / 1000); 27 if (seconds < 60) return "just now"; 28 const minutes = Math.floor(seconds / 60); 29 if (minutes < 60) return `${minutes}m`; 30 const hours = Math.floor(minutes / 60); 31 if (hours < 24) return `${hours}h`; 32 const days = Math.floor(hours / 24); 33 if (days < 30) return `${days}d`; 34 return formatDate(iso); 35} 36 37export function bskyPostUrl(uri: string, handle: string): string { 38 // at://did:plc:.../app.bsky.feed.post/rkey -> https://bsky.app/profile/handle/post/rkey 39 const rkey = uri.split("/").pop() || ""; 40 return `https://bsky.app/profile/${handle}/post/${rkey}`; 41} 42 43export function escapeXml(s: string): string { 44 return s 45 .replace(/&/g, "&amp;") 46 .replace(/</g, "&lt;") 47 .replace(/>/g, "&gt;") 48 .replace(/"/g, "&quot;") 49 .replace(/'/g, "&apos;"); 50}