Initial OSS scaffold from Songs2VID (pre-strip)
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
export type FooterBadgeInput = {
|
||||
name?: string;
|
||||
embedHtml?: string | null;
|
||||
imageUrl?: string | null;
|
||||
linkUrl?: string | null;
|
||||
isActive?: boolean;
|
||||
sortOrder?: number;
|
||||
};
|
||||
|
||||
export type ParsedBadgeEmbed = {
|
||||
imageUrl: string | null;
|
||||
linkUrl: string | null;
|
||||
};
|
||||
|
||||
/** Extract first <a href> + nested/nearby <img src> from pasted badge HTML. */
|
||||
export function parseBadgeEmbedHtml(html: string): ParsedBadgeEmbed {
|
||||
const trimmed = html.trim();
|
||||
if (!trimmed) return { imageUrl: null, linkUrl: null };
|
||||
|
||||
const hrefMatch =
|
||||
trimmed.match(/<a\b[^>]*\bhref\s*=\s*["']([^"']+)["'][^>]*>/i) ??
|
||||
trimmed.match(/href\s*=\s*["']([^"']+)["']/i);
|
||||
const srcMatch =
|
||||
trimmed.match(/<img\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/i) ??
|
||||
trimmed.match(/src\s*=\s*["']([^"']+)["']/i);
|
||||
|
||||
return {
|
||||
linkUrl: hrefMatch?.[1]?.trim() || null,
|
||||
imageUrl: srcMatch?.[1]?.trim() || null,
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeBadgeFields(input: FooterBadgeInput) {
|
||||
const name = (input.name ?? "").trim();
|
||||
const embedHtml = input.embedHtml?.trim() || null;
|
||||
let imageUrl = input.imageUrl?.trim() || null;
|
||||
let linkUrl = input.linkUrl?.trim() || null;
|
||||
|
||||
if (embedHtml) {
|
||||
const parsed = parseBadgeEmbedHtml(embedHtml);
|
||||
if (!imageUrl && parsed.imageUrl) imageUrl = parsed.imageUrl;
|
||||
if (!linkUrl && parsed.linkUrl) linkUrl = parsed.linkUrl;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
embedHtml,
|
||||
imageUrl,
|
||||
linkUrl,
|
||||
isActive: input.isActive ?? true,
|
||||
sortOrder:
|
||||
typeof input.sortOrder === "number" && Number.isFinite(input.sortOrder)
|
||||
? Math.trunc(input.sortOrder)
|
||||
: 0,
|
||||
};
|
||||
}
|
||||
|
||||
export function validateBadgeFields(fields: ReturnType<typeof normalizeBadgeFields>): string | null {
|
||||
if (!fields.name) return "Name is required";
|
||||
if (!fields.embedHtml && !fields.imageUrl) {
|
||||
return "Provide embed HTML or an image URL";
|
||||
}
|
||||
if (fields.imageUrl && !fields.linkUrl && !fields.embedHtml) {
|
||||
return "Link URL is required when using image URL only";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user