183 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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*(?<!\))/g)
 | |
|   ) {
 | |
|     const cleaned = hashtag.replace(/\#/g, "").trim();
 | |
|     if (cleaned.length > 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;
 | |
| }
 |