memorium/lib/string.ts

183 lines
5.1 KiB
TypeScript
Raw Permalink Normal View History

2023-08-06 17:47:26 +02:00
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);
}
2023-08-01 17:50:00 +02:00
export function safeFileName(inputString: string): string {
let fileName = inputString.toLowerCase();
fileName = fileName.replace(/ /g, "_");
fileName = fileName.replace(/[^\w.-]/g, "");
2023-08-04 22:35:25 +02:00
fileName = fileName.replaceAll(":", "");
2023-08-01 17:50:00 +02:00
return fileName;
}
2023-08-02 01:58:03 +02:00
2025-01-25 00:00:04 +01:00
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
}
2023-08-02 01:58:03 +02:00
export function extractHashTags(inputString: string) {
const hashtags = [];
for (
const [hashtag] of inputString.matchAll(/(?:^|\s)#\S*(?<!\))/g)
2023-08-02 01:58:03 +02:00
) {
const cleaned = hashtag.replace(/\#/g, "").trim();
if (cleaned.length > 2) {
hashtags.push(cleaned);
}
2023-08-02 01:58:03 +02:00
}
return hashtags;
}
export const isYoutubeLink = (link: string) => {
try {
const url = new URL(link);
2023-08-04 22:35:25 +02:00
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(/^\//, "");
}
2023-08-04 22:35:25 +02:00
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;
}
2023-08-06 17:47:26 +02:00
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));
2023-08-10 19:16:03 +02:00
export const isString = (input: string | undefined): input is string => {
return typeof input === "string";
};
2023-08-12 18:32:56 +02:00
function componentToHex(c: number) {
if (c <= 1) {
c = Math.round(c * 255);
}
const hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
2023-08-13 02:26:22 +02:00
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();
2023-08-13 02:26:22 +02:00
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;
}
2023-08-12 18:32:56 +02:00
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;
}