Skip to content

Commit

Permalink
Merge pull request #43 from prezly/fix/qrf-113-embeds-vanish-in-edito…
Browse files Browse the repository at this point in the history
…r-in-published

[QRF-113] Strip <script> tags from the injected HTML
  • Loading branch information
riffbyte authored Oct 6, 2022
2 parents 00d659b + b8ba95d commit a905398
Showing 1 changed file with 18 additions and 9 deletions.
27 changes: 18 additions & 9 deletions src/components/HtmlInjection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { HTMLAttributes, ScriptHTMLAttributes, useEffect } from 'react';
import React, { HTMLAttributes, ScriptHTMLAttributes, useEffect, useMemo } from 'react';

interface Props extends HTMLAttributes<HTMLDivElement> {
html: string;
Expand All @@ -8,25 +8,32 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
export function HtmlInjection(props: Props) {
const { html, onError, ...attrs } = props;

useScripts(html, onError);
const strippedHtml = useScripts(html, onError);

return <div {...attrs} dangerouslySetInnerHTML={{ __html: html }} />;
return <div {...attrs} dangerouslySetInnerHTML={{ __html: strippedHtml }} />;
}

function useScripts(html: Props['html'], onError: Props['onError']) {
useEffect(() => {
const [strippedHtml, scriptsAttributes] = useMemo(() => {
const container = document.createElement('div');
container.innerHTML = html;

const scripts: ScriptHTMLAttributes<HTMLScriptElement>[] = Array.from(
container.getElementsByTagName('script'),
).map((script) => {
const scripts = Array.from(container.getElementsByTagName('script'));

const scriptsAttributes: ScriptHTMLAttributes<HTMLScriptElement>[] = scripts.map((script) => {
return Array.from(script.attributes).reduce((agg, { name, value }) => ({ ...agg, [name]: value }), {});
});

scripts.forEach((script) => script.remove());

const strippedHtml = container.innerHTML;
container.remove();

scripts.forEach((attributes) => {
return [strippedHtml, scriptsAttributes];
}, [html]);

useEffect(() => {
scriptsAttributes.forEach((attributes) => {
if (attributes.src && document.querySelector(`script[src="${attributes.src}"]`)) {
return;
}
Expand All @@ -43,7 +50,9 @@ function useScripts(html: Props['html'], onError: Props['onError']) {
}

return;
}, [html]);
}, [scriptsAttributes]);

return strippedHtml;
}

function setScriptAttributes(script: HTMLScriptElement, attributes: ScriptHTMLAttributes<HTMLScriptElement>): void {
Expand Down

0 comments on commit a905398

Please sign in to comment.