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
SL-528: Parse start_html using ::HTML to preserve expanded tags and fix App Lab rendering #50452
Conversation
Can we add a unit test to this PR? It seems the ideal situation for one. |
Yes, definitely! |
:blockly, | ||
name: 'test localized_start_html', | ||
) | ||
start_html = '<div><button id="leftBottomButton" style="padding: 0px; margin: 0px; border-style: solid; background-color: rgb(68, 44, 46); border-radius: 20px; border-width: 0px; border-color: rgb(255, 255, 255); color: rgb(255, 255, 255); font-family: Verdana, Geneva, sans-serif; font-size: 15px; position: absolute; left: 10px; top: 250px; background-size: contain; background-position: 50% 50%; background-repeat: no-repeat; width: 45px; height: 190px;" data-canonical-image-url="icon://fa-long-arrow-left" data-icon-color="#ffffff"></button><label style="margin: 0px; padding: 2px; line-height: 1; overflow: hidden; overflow-wrap: break-word; max-width: 320px; border-style: solid; background-color: rgb(254, 234, 230); border-width: 0px; border-color: rgb(255, 255, 255); color: rgb(68, 44, 46); font-family: Arial, Helvetica, sans-serif; position: absolute; left: 0px; top: 4.44089e-16px; border-radius: 4px; height: 40px; width: 320px; font-size: 36px; text-rendering: optimizespeed;" id="appName"> Outfit Picker</label></div>' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we reduce this to a more minimal repro case? It might be a bit easier to understand what we are verifying...
start_html_xml.serialize(save_with: XML_OPTIONS).strip | ||
# NO_EMPTY_TAGS used because <element /> blocks fail to render correctly but | ||
# <element></element> works, see: https://codedotorg.atlassian.net/browse/SL-528. | ||
# TODO: Should we add UTF-8 encoding? We have it here: https://github.com/code-dot-org/code-dot-org/blob/staging/dashboard/app/models/levels/blockly.rb#L520. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we put the long URL on a new line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use Nokogiri::HTML.fragment(start_html, &:noblanks)
instead of Nokogiri::XML.fragment(start_html, &:noblanks)
.
The start_html is a well-formed html fragment that gets injected as into the level document.
It doesn't make sense to use XML here, as it is inducing undesired changes in the html tags (not only creating self-enclosing tags, but closing tags).
Yep, going to change based on our conversation. I don't think we need the argument to |
Exactly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! This switch to HTML parsing fixes multiple issues. Thanks!
The following PR fixes several instances in which folks are seeing App Lab levels with jumbled/misplaced UI elements on sample applications (see screenshots below). The issue is that the call to
Nokogiri::XML
turns expanded tags in our HTML (ex.<button ...></button>
) to self-enclosing tags (ex.<button ... />
), and for some reason, this "breaks" the element rendering.It turns out the config option that fixes this issue is already in place at another point in our code. Still, I did not discover that the
Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS
config value was used elsewhere until I finished my investigation.I diagnosed by looking at the diff in the HTML at every step in the
localized_start_html
. Thestart_html
that serves as the argument to this function renders correctly, but as soon as we callstart_html_xml = Nokogiri::XML(start_html, &:noblanks)
, thestart_html_xml
reproduces the bug in an HTML renderer. Since Nokogiri can perform its operations on the self-enclosing tags, we don't need to expand the tags until before we return them fromlocalized_start_html
. This is good because the config option we need to pass to expand all HTML tags is a valid argument tostart_html_xml.serialize
but cannot be passed toNokogiri::XML
to keep them from getting collapsed in the first place.NOTE: This config option will expand all tags, including any that were self-closing in our
start_html
. Theoretically, expanding tags meant to be self-enclosing could also cause issues, but expanding all tags seems to solve most of our problems (see screenshots below).For posterity/documentation, sparklemotion/nokogiri#2324 describes a similar issue, but in the opposite direction (self-closing tags being converted to expanded tags), and is the issue that eventually led me to my fix.
I do not know why using self-enclosing tags instead of expanded tags would cause the issue, but given the volume of tickets we're receiving, it seems worth getting a fix out while we continue the investigation.
Links
Jira tickets:
https://codedotorg.atlassian.net/browse/SL-528
https://codedotorg.atlassian.net/browse/P20-43
Zendesk tickets:
https://codeorg.zendesk.com/agent/tickets/427471
https://codeorg.zendesk.com/agent/tickets/424893
https://codeorg.zendesk.com/agent/tickets/430408
Testing story
Before
Note: These screenshots were generated by resetting version history while the page is in Danish on studio.code.org. I have reproduced this with other languages, including Spanish and French.
https://studio.code.org/s/csp5-2022/lessons/2/levels/1
https://studio.code.org/s/csp5-2022/lessons/10/levels/1
https://studio.code.org/s/csp7-2022/lessons/4/levels/2
https://studio.code.org/s/csp7-2022/lessons/3/levels/6
After
Note: These screenshots were generated by resetting version history while the page is in Danish on localhost-studio.code.org:3000. I have reproduced this with other languages, including Spanish and French.
http://localhost-studio.code.org:3000/s/csp5-2022/lessons/2/levels/1
http://localhost-studio.code.org:3000/s/csp5-2022/lessons/10/levels/1
http://localhost-studio.code.org:3000/s/csp7-2022/lessons/4/levels/2
http://localhost-studio.code.org:3000/s/csp7-2022/lessons/3/levels/6
The screenshot above is not totally fixed because of another bug with how Nokogiri handles spaces, but it is much better than the original! I will file a follow-up ticket and link here.
Deployment strategy
Follow-up work
Privacy
Security
Caching
PR Checklist: