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

html_to_vdom transform to remove html/body but preserve head content #832

Merged
merged 29 commits into from
Dec 1, 2022

Conversation

Archmonger
Copy link
Contributor

@Archmonger Archmonger commented Nov 9, 2022

There's currently some awkwardness in converting django views to VDOM, due to the fact that the head content is never loaded into the page.

For example, CSS/JS that is within <head> is simply never added to the page.

This PR makes html_to_vdom use the same approach browsers use when merging two HTML/body node trees. Namely, the contents of the <head> and <body> tags are directly spit out onto the page, while removing those top level tags themselves.

Checklist

Please update this checklist as you complete each item:

  • Tests have been included for all bug fixes or added functionality.
  • The changelog.rst has been updated with any significant changes.
  • GitHub Issues which may be closed by this Pull Request have been linked.

@Archmonger Archmonger marked this pull request as ready for review November 9, 2022 09:09
@Archmonger Archmonger requested a review from rmorshea November 9, 2022 09:09
@rmorshea
Copy link
Collaborator

rmorshea commented Nov 9, 2022

Could this be implemented as a transform instead? I suppose one could imagine using the VDOM data structures as a way to create normal HTML templates rather than injecting it into the page in the way IDOM does. Thus, retaining the head and body elements could be useful in that case.

@Archmonger
Copy link
Contributor Author

Archmonger commented Nov 9, 2022

I don't actually believe there's any use case for people templating HTML/Body/head tags within IDOM.

Using scripts outside of the <html> tag is not within HTML5 spec, so browsers are free to reject that behavior at any time. We shouldn't expect all browsers to support this.

And the <html> and <body> tag gets auto constructed (on a lot of browsers) if it doesn't exist upon first paint so we might get into some messy territory if we support that.

If we want to support <html>/<body> IDOM rendering, in my opinion that's a separate PR that will require some hacky JavaScript. Even then, I don't see a good cross-browser way to do this.

@rmorshea
Copy link
Collaborator

I don't think we should bake this into html_to_vdom. It's not clear to me that this approach to dealing with html/head/body is universally applicable. For example, in the future, we could allow users to declare head elements in IDOM by leveraging a tool like react-helmet. In which case, we'd actually want to preserve the head/body distinction. Thus I think this should be implemented as a transform. One that could be included in IDOM core given its broad, but not necessarily universal, appeal.

@Archmonger
Copy link
Contributor Author

Given that helmet exists, I'm okay with that. On a different note, is there truly a purpose for us to keep the idom.html.html and idom.html.body representations?

@rmorshea
Copy link
Collaborator

rmorshea commented Nov 10, 2022

We could, though there's not much cost to having them there either aside from the extra make_vdom_constructor call. If you feel strongly about it, I'd be ok removing them though.

@Archmonger
Copy link
Contributor Author

It has been converted to a transform.

@Archmonger Archmonger changed the title Insert head content into html_to_vdom html_to_vdom transform to remove html/body but preserve head content Nov 14, 2022
@Archmonger
Copy link
Contributor Author

Let me know if deleting body is something you want to commit to. I personally think removing it helps set expectations, since currently I don't see any way to use it.

rmorshea
rmorshea previously approved these changes Nov 19, 2022
src/idom/utils.py Outdated Show resolved Hide resolved
@Archmonger
Copy link
Contributor Author

Archmonger commented Nov 20, 2022

I didn't have it set to VdomDict because mypy didn't like that for some reason. Was easier to set as a generic dict than figure it out at the time.

If we wanna go back to VdomDict we'll need to fix that.

@Archmonger
Copy link
Contributor Author

Archmonger commented Nov 23, 2022

I reverted the VdomDict type hint change since I wasn't entirely sure what was wrong.

Let me know if you're comfortable with that.

@rmorshea
Copy link
Collaborator

rmorshea commented Nov 30, 2022

Could this transform be more simply written as?

def del_html_body_transform(vdom: VdomDict) -> VdomDict:
    """Removes ``<html>``, ``<head>``, and ``<body>`` elements.

    This is accomplished by turning the aforementioned elements into fragments.
    See :func:`idom.html._` for more details on element fragments.

    .. note::

        Intended for use with :func:`html_to_vdom`.

    Parameters:
        vdom:
            The VDOM dictionary to transform.
    """
    return {**vdom, "tagName": ""} if vdom["tagName"] in {"html", "body", "head"} else vdom

@Archmonger
Copy link
Contributor Author

Yeah.

Results in an uglier final VDOM with a bunch of fragments, but functionally would work the same when rendered.

@Archmonger Archmonger requested a review from rmorshea November 30, 2022 06:28
src/idom/utils.py Outdated Show resolved Hide resolved
@rmorshea rmorshea merged commit 9c3c300 into reactive-python:main Dec 1, 2022
@Archmonger Archmonger deleted the html_to_vdom_head_content branch December 2, 2022 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants