Skip to content

feat: add support for mixed html/js content #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
enable interaction in Preview panel through script tag in html (#10)
Bianca Del Carretto committed Jun 10, 2020
commit ce93e105bbba5985b1e5029f6663466699aff386
36 changes: 34 additions & 2 deletions src/components/Preview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react';
import React, { useState, useEffect, useRef, useMemo } from 'react';
import Scrollable from './Scrollable';
import PreviewHint from './PreviewHint';
import AddHtml from './AddHtml';
@@ -34,6 +34,36 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) {

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

const scripts = useMemo(() => {
const container = document.createElement('div');
container.innerHTML = markup;
const scriptsCollections = container.getElementsByTagName('script');
return Array.from(scriptsCollections).map((script) => script.innerHTML);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also parses script elements of other types than javascript. For example <script type="text/css">. Type attributes for script elements default to text/javascript, so we should only extract script elements without a type attribute, or with a type === "text/javascript"

<script type="text/javascript">
  document.getElementById('btn').addEventListener('click', () => {
    alert('click');
  });
</script>

See also this repl.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! I am going to fix it again!

}, [markup]);

const actualMarkup = useMemo(
() =>
scripts.length
? scripts.reduce(
(html, script) => html.replace(`<script>${script}</script>`, ''),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't remove script elements that specify the type attribute. Type attributes for script elements default to text/javascript, but it's still a valid attribute to provide. 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, totally right! I am going to fix it!

markup,
)
: markup,
[scripts, markup],
);

useEffect(() => {
if (scripts.length) {
try {
scripts.forEach((script) => {
window.eval(script);
});
} catch {
return;
}
}
}, [scripts]);

useEffect(() => {
setRoles(Object.keys(accessibleRoles || {}).sort());
}, [accessibleRoles]);
@@ -98,7 +128,9 @@ function Preview({ markup, accessibleRoles, elements, dispatch }) {
onClick={handleClick}
onMouseMove={handleMove}
ref={htmlRoot}
dangerouslySetInnerHTML={{ __html: markup }}
dangerouslySetInnerHTML={{
__html: actualMarkup,
}}
/>
</Scrollable>
</div>