fix(frontend): execute scripts in custom HTML modules (#59)
dangerouslySetInnerHTML never executes embedded <script> tags, so admin- supplied sidebar/login/footer modules silently dropped scripts. Re-create each script as a fresh DOM node after injection so it executes normally. Content remains admin-trusted only; the admin hint now says scripts run. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>pull/3587/head
parent
0aed15de29
commit
df2d6027db
@ -0,0 +1,33 @@
|
|||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
export interface CustomHTMLContentProps {
|
||||||
|
html: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomHTMLContent renders administrator-supplied HTML. Scripts inside the
|
||||||
|
// markup do not run when injected via innerHTML, so each <script> element is
|
||||||
|
// re-created as a fresh node — dynamically inserted scripts execute normally.
|
||||||
|
// The content is trusted by definition (only admins can configure it).
|
||||||
|
const CustomHTMLContent = ({ html }: CustomHTMLContentProps) => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const container = ref.current;
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.querySelectorAll("script").forEach((oldScript) => {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
Array.from(oldScript.attributes).forEach((attr) => {
|
||||||
|
script.setAttribute(attr.name, attr.value);
|
||||||
|
});
|
||||||
|
script.textContent = oldScript.textContent;
|
||||||
|
oldScript.replaceWith(script);
|
||||||
|
});
|
||||||
|
}, [html]);
|
||||||
|
|
||||||
|
return <div ref={ref} dangerouslySetInnerHTML={{ __html: html }} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomHTMLContent;
|
||||||
Loading…
Reference in new issue