svgo
svgo copied to clipboard
SVGO creates invalid self-closing tags inside `<foreignObject>` elements
Describe the bug
When an empty tag is present inside of a <foreignObject>
element, SVGO converts it to a self-closing tag. This results in tags that are invalid HTML and are misinterpreted by the browser.
To Reproduce Steps to reproduce the behavior:
- Run
svgo test.svg --pretty --indent=2
, wheretest.svg
:
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px" viewBox="0 0 10 10">
<foreignObject x="0" y="0" width="10" height="10" style="font-size:2px">
<p style="margin-top:0">
<span style="height:4px;display:inline-block"></span>
Some text.
</p>
</foreignObject>
</svg>
- Observe the result, which is:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 10 10">
<foreignObject width="10" height="10" x="0" y="0" style="font-size:2px">
<p style="margin-top:0">
<span style="height:4px;display:inline-block"/>
Some text.
</p>
</foreignObject>
</svg>
Note that the empty <span>
element has been converted to a self-closing tag. This results in invalid HTML, since <span>
is not a void element. The browser actually interprets the self-closing tag as an opening tag, and then automatically closes the tag later on. This is essentially equivalent to:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 10 10">
<foreignObject width="10" height="10" x="0" y="0" style="font-size:2px">
<p style="margin-top:0">
<span style="height:4px;display:inline-block">
Some text.
</span>
</p>
</foreignObject>
</svg>
(See here for more information.)
When viewing the SVG in a browser, keep in mind that <foreignObject>
elements will not be rendered unless the SVG is inside of an HTML page. To fix this, add <html>
tags and save the file as an HTML file.
Expected behavior
Inside <foreignObject>
elements, empty elements should not be converted to self-closing tags.
Version info:
- SVGO Version: 3.0.2
- NodeJs Version: v19.2.0
- OS: Linux
Turns out this is a duplicate of #1473. That issue also points out that SVGO treats whitespace inside <foreignObject>
elements incorrectly, something I hadn't noticed initially, but is still an issue in version 3.0.2.
I don't think the self-closing tag is invalid. The content within a <foreignObject>
has to be XML, which means it's XHTML, not HTML, so <span/>
should be equivalent to <span></span>
.
There is still a problem with whitespace being trimmed, and as pointed out in #1678, the safest solution is to preserve all white space within a <foreignObject>
.
Yep, <foreignObject>
is a different world, which SVGO knows nothing about. That's not a bug, since special handling of <foreignObject>
was never implemented (as far as I concerned). PRs are welcome.