Initial OSS scaffold from Songs2VID (pre-strip)

This commit is contained in:
Songs2VID OSS
2026-08-03 06:15:05 +02:00
commit 7d7043b150
195 changed files with 25023 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
"use client";
import { useEffect, useRef } from "react";
type PublicBadge = {
id: string;
name: string;
embedHtml: string | null;
imageUrl: string | null;
linkUrl: string | null;
};
/**
* Renders a badge embed safely inside the marquee slot.
* Prefer structured image+link; fall back to HTML (re-executing scripts when present).
*/
export function BadgeEmbed({ badge }: { badge: PublicBadge }) {
const hostRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const host = hostRef.current;
if (!host) return;
host.replaceChildren();
if (badge.imageUrl && badge.linkUrl) {
const a = document.createElement("a");
a.href = badge.linkUrl;
a.target = "_blank";
a.rel = "noopener noreferrer";
a.title = badge.name;
a.className = "badge-marquee-link";
const img = document.createElement("img");
img.src = badge.imageUrl;
img.alt = badge.name;
img.loading = "lazy";
img.decoding = "async";
a.appendChild(img);
host.appendChild(a);
return;
}
if (!badge.embedHtml) return;
const template = document.createElement("template");
template.innerHTML = badge.embedHtml.trim();
const scripts: HTMLScriptElement[] = [];
template.content.querySelectorAll("script").forEach((node) => {
scripts.push(node.cloneNode(true) as HTMLScriptElement);
node.remove();
});
host.appendChild(template.content.cloneNode(true));
for (const oldScript of scripts) {
const script = document.createElement("script");
for (const attr of oldScript.attributes) {
script.setAttribute(attr.name, attr.value);
}
if (oldScript.textContent) script.textContent = oldScript.textContent;
host.appendChild(script);
}
}, [badge.embedHtml, badge.imageUrl, badge.linkUrl, badge.name]);
return (
<div
ref={hostRef}
className="badge-marquee-slot"
data-badge-id={badge.id}
data-badge-name={badge.name}
/>
);
}