Initial OSS scaffold from Songs2VID (pre-strip)
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user