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

Avoid parsing into DOM when rendering live components #2839

Merged
merged 4 commits into from
Oct 3, 2023

Conversation

chrismccord
Copy link
Member

No description provided.

@chrismccord chrismccord merged commit f54eea9 into main Oct 3, 2023
@chrismccord chrismccord deleted the cm-optimize-parsing branch October 3, 2023 00:38
while(pos < html.length){
let maybeStart = html.indexOf("<", pos)
if(maybeStart === -1){ break }
if(maybeStart >= 0 && html.charAt(maybeStart + 1) !== "!"){
Copy link
Member

Choose a reason for hiding this comment

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

I think we can remove maybeStart >= 0, right?

let pos = 0
while(pos < html.length){
let maybeStart = html.indexOf("<", pos)
if(maybeStart === -1){ break }
Copy link
Member

Choose a reason for hiding this comment

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

Should you throw instead? Otherwise html.slice() later will fail in confusing ways.

pos += html.indexOf("-->", pos)
}

let commentBefore = tagStartsAt === 0 ? null : html.slice(0, tagStartsAt).trim()
Copy link
Member

Choose a reason for hiding this comment

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

  let commentBefore = html.slice(0, tagStartsAt).trim()

then you don't need to deal with nulls later.

let tagNamesEndsAt
for(let i = 1; i < html.length; i++){
let char = html.charAt(i)
if([">", " ", "\n", "\t", "\r"].indexOf(char) >= 0 || (char === "!" && html.charAt(i + 1) === ">")){
Copy link
Member

@josevalim josevalim Oct 3, 2023

Choose a reason for hiding this comment

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

What is char === "!" about?

}

let tag = html.slice(1, tagNamesEndsAt)
let tagOpenEndsAt = html.indexOf(">")
Copy link
Member

Choose a reason for hiding this comment

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

This does not work because you may have ">" inside an attribute. :D That's why my original suggestion in the gist was to have a list of void tags. Because if you want to check if the tag is actually void, you will get pretty close to having to parse all HTML!

if(isVoid){
contentAfter = html.slice(tagOpenEndsAt + 1) || null
} else {
closingTag = `</${tag}>`
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 does not work, because you may have this: <div>Foo<div></div>Baz</div> and now you will get the closing to the wrong div.

The approach I took in the gist was to check if the html ends with -->, if so, you need to remove the comments at the end. Once comments are stripped, the closing tag will necessarily be at the end of the document.

@@ -17,6 +17,66 @@ import {
isCid,
} from "./utils"

export let modifyRoot = (html, attrs, innerHTML) => {
html = html.trimStart()
Copy link
Member

Choose a reason for hiding this comment

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

You shouldn't need trimStart().

let skip = onlyCids && !onlyCids.has(cid)
let attrs = {[PHX_COMPONENT]: cid, id: `${this.parentViewId()}-${cid}`}
Copy link
Member

Choose a reason for hiding this comment

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

Could we use the new phx-magic-id already and battle test it within components? This way we don't need to mangle the ID either in modifyRoot.


let newAttrs = []
Object.keys(attrs).forEach(attr => {
if(!tagOpenContent.includes(`${attr}="`)){ newAttrs.push([attr, attrs[attr]]) }
Copy link
Member

Choose a reason for hiding this comment

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

This can also have false positives, albeit more unlikely. However, my suggestion is to not use the ID at all, let's just inject new/private attributes.

chrismccord added a commit that referenced this pull request Oct 4, 2023
chrismccord added a commit that referenced this pull request Oct 4, 2023
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