diff --git a/src/components/Editor.js b/src/components/Editor.js index 2c8e8a0a..5cef7f9f 100644 --- a/src/components/Editor.js +++ b/src/components/Editor.js @@ -1,6 +1,8 @@ import React, { useRef, useEffect } from 'react'; import 'codemirror/mode/javascript/javascript'; import 'codemirror/mode/xml/xml'; +import 'codemirror/mode/css/css'; +import 'codemirror/mode/htmlmixed/htmlmixed'; import 'codemirror/addon/edit/closetag'; import 'codemirror/addon/fold/xml-fold'; import 'codemirror/addon/scroll/simplescrollbars'; @@ -27,6 +29,11 @@ const options = { mode: { name: 'text/html', multilineTagIndentPastTag: false }, }, + htmlmixed: { + ...baseOptions, + mode: { name: 'htmlmixed' }, + }, + javascript: { ...baseOptions, mode: 'javascript', diff --git a/src/components/MarkupEditor.js b/src/components/MarkupEditor.js index 7c86a6a9..d9da0b0a 100644 --- a/src/components/MarkupEditor.js +++ b/src/components/MarkupEditor.js @@ -16,7 +16,7 @@ function MarkupEditor({ markup, dispatch }) {
{ + const container = document.createElement('div'); + container.innerHTML = markup; + const scriptsCollections = container.getElementsByTagName('script'); + const jsScripts = Array.from(scriptsCollections).filter( + (script) => script.type === 'text/javascript' || script.type === '', + ); + setScripts((scripts) => [ + ...scripts.filter((script) => + jsScripts + .map((jsScript) => jsScript.innerHTML) + .includes(script.innerHTML), + ), + ...jsScripts + .filter( + (jsScript) => + !scripts + .map((script) => script.innerHTML) + .includes(jsScript.innerHTML), + ) + .map((jsScript) => ({ + scriptCode: jsScript.innerHTML, + toBeRemoved: jsScript.outerHTML, + evaluated: false, + })), + ]); + }, [markup, setScripts]); + + const actualMarkup = useMemo( + () => + scripts.length + ? scripts.reduce( + (html, script) => html.replace(script.toBeRemoved, ''), + markup, + ) + : markup, + [scripts, markup], + ); + + useEffect(() => { + if (htmlRoot.current && highlighted) { + scripts + .filter((script) => !script.evaluated) + .forEach((script) => { + try { + script.evaluated = true; + const executeScript = new Function(script.scriptCode); + executeScript(); + } catch (e) { + alert('Failing script inserted in markup!'); + } + }); + } + }, [highlighted, scripts, htmlRoot.current]); + useEffect(() => { setRoles(Object.keys(accessibleRoles || {}).sort()); }, [accessibleRoles]); @@ -98,7 +154,9 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) { onClick={handleClick} onMouseMove={handleMove} ref={htmlRoot} - dangerouslySetInnerHTML={{ __html: markup }} + dangerouslySetInnerHTML={{ + __html: actualMarkup, + }} />