Skip to content
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

Treat tags.script like an HTML dependency inside of JSXTag #27

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions htmltools/_jsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
HTML,
MetadataNode,
HTMLDependency,
head_content,
)
from ._versions import versions

Expand Down Expand Up @@ -123,6 +124,12 @@ def tagify(self) -> Tag:
# metadata nodes. This could be done in two separate passes, but it's more
# efficient to do it in one pass.
def tagify_tagifiable_and_get_metadata(x: Any) -> Any:
if isinstance(x, Tag) and x.name == "script":
# React.createElement("script") won't invoke it's contents in the same
# way ordinary HTML tags do, but we can circumvent that by 'hoisting' it
# as head_content.
metadata_nodes.append(head_content(x))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If we move forward with this, we'll want to have something like head_content(x, dedup=False) to make sure the <script> executes everytime, as it normally would in normal HTML

x = MetadataNode()
if isinstance(x, Tagifiable) and not isinstance(x, (Tag, JSXTag)):
x = x.tagify()
else:
Expand Down
20 changes: 17 additions & 3 deletions tests/test_jsx_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def test_jsx_tags():
jsx("`childexpression`"),
Foo(),
[Foo(), Bar()],
tags.script("alert('hello')"),
TagList(Foo(), Bar()),
span(Foo(span()), Bar()),
int=1,
Expand All @@ -84,9 +85,19 @@ def test_jsx_tags():
string="string",
list=[1, 2, 3],
)
assert str(x) == textwrap.dedent(
assert HTMLDocument(x).render()["html"] == textwrap.dedent(
"""\
<script type="text/javascript" data-needs-render="">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="application/html-dependencies">react[%s];react-dom[%s];headcontent_eb156e81fa07b6cf22e580f33fa4f1e4b3ee0431[0.0]</script>
<script src="lib/react-%s/react.production.min.js"></script>
<script src="lib/react-dom-%s/react-dom.production.min.js"></script>
<script>alert('hello')</script>
</head>
<body>
<script type="text/javascript" data-needs-render="">
(function() {
var container = new DocumentFragment();
ReactDOM.render(
Expand Down Expand Up @@ -115,7 +126,10 @@ def test_jsx_tags():
thisScript.after(container);
thisScript.removeAttribute('data-needs-render');
})();
</script>"""
</script>
</body>
</html>"""
% (react_ver, react_dom_ver, react_ver, react_dom_ver)
)

x = Foo(
Expand Down