Skip to content

Commit 85c240c

Browse files
authored
feat: add support for mixed html/js content (#128)
With the support of mixed html/js content, the preview area also becomes interactive!
1 parent 1b38372 commit 85c240c

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

src/components/Editor.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { useRef, useEffect } from 'react';
22
import 'codemirror/mode/javascript/javascript';
33
import 'codemirror/mode/xml/xml';
4+
import 'codemirror/mode/css/css';
5+
import 'codemirror/mode/htmlmixed/htmlmixed';
46
import 'codemirror/addon/edit/closetag';
57
import 'codemirror/addon/fold/xml-fold';
68
import 'codemirror/addon/scroll/simplescrollbars';
@@ -27,6 +29,11 @@ const options = {
2729
mode: { name: 'text/html', multilineTagIndentPastTag: false },
2830
},
2931

32+
htmlmixed: {
33+
...baseOptions,
34+
mode: { name: 'htmlmixed' },
35+
},
36+
3037
javascript: {
3138
...baseOptions,
3239
mode: 'javascript',

src/components/MarkupEditor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function MarkupEditor({ markup, dispatch }) {
1616
<div className="h-full w-full flex flex-col">
1717
<div className="markup-editor flex-auto relative overflow-hidden">
1818
<Editor
19-
mode="html"
19+
mode="htmlmixed"
2020
initialValue={markup}
2121
onLoad={onLoad}
2222
onChange={onChange}

src/components/Preview.js

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useRef } from 'react';
1+
import React, { useState, useEffect, useRef, useMemo } from 'react';
22
import Scrollable from './Scrollable';
33
import PreviewHint from './PreviewHint';
44
import AddHtml from './AddHtml';
@@ -25,6 +25,7 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) {
2525
// Indicating that the `parsed` element can be highlighted again.
2626
const [highlighted, setHighlighted] = useState(false);
2727
const [roles, setRoles] = useState([]);
28+
const [scripts, setScripts] = useState([]);
2829
const htmlRoot = useRef();
2930

3031
const { suggestion } = getQueryAdvise({
@@ -34,6 +35,61 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) {
3435

3536
// TestingLibraryDom?.getSuggestedQuery(highlighted, 'get').toString() : null
3637

38+
useEffect(() => {
39+
const container = document.createElement('div');
40+
container.innerHTML = markup;
41+
const scriptsCollections = container.getElementsByTagName('script');
42+
const jsScripts = Array.from(scriptsCollections).filter(
43+
(script) => script.type === 'text/javascript' || script.type === '',
44+
);
45+
setScripts((scripts) => [
46+
...scripts.filter((script) =>
47+
jsScripts
48+
.map((jsScript) => jsScript.innerHTML)
49+
.includes(script.innerHTML),
50+
),
51+
...jsScripts
52+
.filter(
53+
(jsScript) =>
54+
!scripts
55+
.map((script) => script.innerHTML)
56+
.includes(jsScript.innerHTML),
57+
)
58+
.map((jsScript) => ({
59+
scriptCode: jsScript.innerHTML,
60+
toBeRemoved: jsScript.outerHTML,
61+
evaluated: false,
62+
})),
63+
]);
64+
}, [markup, setScripts]);
65+
66+
const actualMarkup = useMemo(
67+
() =>
68+
scripts.length
69+
? scripts.reduce(
70+
(html, script) => html.replace(script.toBeRemoved, ''),
71+
markup,
72+
)
73+
: markup,
74+
[scripts, markup],
75+
);
76+
77+
useEffect(() => {
78+
if (htmlRoot.current && highlighted) {
79+
scripts
80+
.filter((script) => !script.evaluated)
81+
.forEach((script) => {
82+
try {
83+
script.evaluated = true;
84+
const executeScript = new Function(script.scriptCode);
85+
executeScript();
86+
} catch (e) {
87+
alert('Failing script inserted in markup!');
88+
}
89+
});
90+
}
91+
}, [highlighted, scripts, htmlRoot.current]);
92+
3793
useEffect(() => {
3894
setRoles(Object.keys(accessibleRoles || {}).sort());
3995
}, [accessibleRoles]);
@@ -99,7 +155,9 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) {
99155
onClick={handleClick}
100156
onMouseMove={handleMove}
101157
ref={htmlRoot}
102-
dangerouslySetInnerHTML={{ __html: markup }}
158+
dangerouslySetInnerHTML={{
159+
__html: actualMarkup,
160+
}}
103161
/>
104162
</Scrollable>
105163
</div>

0 commit comments

Comments
 (0)