import { resources } from "@lib/resources.ts"; export function formatDate(date: Date): string { const options = { year: "numeric", month: "long", day: "numeric" } as const; return new Intl.DateTimeFormat("en-US", options).format(date); } export function safeFileName(inputString: string): string { let fileName = inputString.toLowerCase(); fileName = fileName.replace(/ /g, "_"); fileName = fileName.replace(/[^\w.-]/g, ""); fileName = fileName.replaceAll(":", ""); return fileName; } export function toUrlSafeString(input: string): string { return input .trim() // Remove leading and trailing whitespace .toLowerCase() // Convert to lowercase .replace(/[^a-z0-9\s-]/g, "") // Remove non-alphanumeric characters except spaces and hyphens .replace(/\s+/g, "-") // Replace spaces with hyphens .replace(/-+/g, "-"); // Remove consecutive hyphens } export function extractHashTags(inputString: string) { const hashtags = []; for ( const [hashtag] of inputString.matchAll(/(?:^|\s)#\S*(? 2) { hashtags.push(cleaned); } } return hashtags; } export const isYoutubeLink = (link: string) => { try { const url = new URL(link); return ["youtu.be", "youtube.com", "www.youtube.com"].includes( url.hostname, ); } catch (_err) { return false; } }; export function extractYoutubeId(link: string) { const url = new URL(link); if (url.searchParams.has("v")) { const id = url.searchParams.get("v"); if (id?.length && id.length > 4) { return id; } } return url.pathname.replace(/^\//, ""); } export async function hash(message: string) { const data = new TextEncoder().encode(message); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join( "", ); return hashHex; } // Helper function to calculate SHA-256 hash export async function sha256(input: string) { const encoder = new TextEncoder(); const data = encoder.encode(input); const hashBuffer = await crypto.subtle.digest("SHA-256", data); return base64urlencode(new Uint8Array(hashBuffer)); } // Helper function to encode a byte array as a URL-safe base64 string function base64urlencode(data: Uint8Array) { const base64 = btoa(String.fromCharCode(...data)); return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); } export function getCookie(name: string): string | null { if (typeof document === "undefined") return null; const nameLenPlus = name.length + 1; return document.cookie .split(";") .map((c) => c.trim()) .filter((cookie) => { return cookie.substring(0, nameLenPlus) === `${name}=`; }) .map((cookie) => { return decodeURIComponent(cookie.substring(nameLenPlus)); })[0] || null; } const resourcePrefixes = Object.values(resources).map((v) => v.prefix).filter( (s) => s.length > 2, ); export const isLocalImage = (src: string) => resourcePrefixes.some((p) => src.startsWith(p)); export const isString = (input: string | undefined): input is string => { return typeof input === "string"; }; function componentToHex(c: number) { if (c <= 1) { c = Math.round(c * 255); } const hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; } export function getTimeCacheKey() { const d = new Date(); const year = d.getFullYear(); const month = d.getMonth().toString(); const day = d.getDate().toString(); const hour = d.getHours().toString(); const minute = d.getMinutes().toString(); const seconds = d.getSeconds().toString(); return `${year}:${month}:${day}:${hour}:${minute}:${seconds}`; } export function parseTimeCacheKey(key: string) { const [_year, _month, _day, _hour, _minute, _second] = key.split(":") .slice(1).map((s) => parseInt(s)); const d = new Date(); d.setFullYear(_year); d.setMonth(_month); d.setDate(_day); d.setHours(_hour); d.setMinutes(_minute); d.setSeconds(_second); return d; } export function rgbToHex(r: number, g: number, b: number) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); } export function removeMarkdownFormatting(text: string): string { // Remove code blocks text = text.replace(/```[\s\S]*?```/g, ""); // Remove inline code text = text.replace(/`([^`]+)`/g, "$1"); // Remove images text = text.replace(/!\[.*?\]\(.*?\)/g, ""); // Remove links text = text.replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1"); // Remove bold and italic formatting text = text.replace(/(\*\*|__)(.*?)\1/g, "$2"); // Bold text = text.replace(/(\*|_)(.*?)\1/g, "$2"); // Italic // Remove strikethrough text = text.replace(/~~(.*?)~~/g, "$1"); // Remove headings text = text.replace(/^#{1,6}\s*(.+)$/gm, "$1"); // Remove blockquotes text = text.replace(/^>\s*/gm, ""); // Remove unordered list markers text = text.replace(/^[-*+]\s+/gm, "-"); // Remove ordered list markers text = text.replace(/^\d+\.\s+/gm, ""); // Remove horizontal rules text = text.replace(/^---+$/gm, ""); return text; }