innerHTML <code> contents is escaped
nbianca opened this issue · 2 comments
Hello,
I am using diffhtml's innerHTML with <code> elements and the contents is escaped even if it is not necessary.
<html>
<head></head>
<body>
<div id="example1"></div>
<div id="example2"></div>
</body>
</html>
import { innerHTML } from '//diffhtml.org/es';
const html = `<code><b>test</b></code>`;
document.getElementById('example1').innerHTML = html;
innerHTML(document.getElementById('example2'), html);
will output
<html>
<head></head>
<body>
<div id="example1"><code><b>test</b></code></div>
<div id="example2"><code><b>test</b></code></div>
</body>
</html>
but I expected
<html>
<head></head>
<body>
<div id="example1"><code><b>test</b></code></div>
<div id="example2"><code><b>test</b></code></div>
</body>
</html>
I think the problem is related to the HTML parser:
window.diff.Internals.parse('<code><b>test</b></code>').childNodes[0].childNodes[0]
// =>
{
"rawNodeName":"#text",
"nodeName":"#text",
"nodeValue":"<b>test</b>",
"nodeType":3,
"key":"",
"childNodes":[],
"attributes":{}
}
This is intentional since typically <code>
is designed to display code and not necessarily render markup. I can see how this is problematic as innerHTML
and outerHTML
are designed to work like their DOM counterparts, and they are differing here. I will look into supporting unescaped markup.
In the meanwhile you can work around this using a transition handler:
import { addTransitionState } from '//diffhtml.org/es';
addTransitionState('attached', el => {
if (el.nodeName.toLowerCase() === 'code') {
// Decode HTML entities for code tags
el.innerHTML = el.innerText;
}
});
@nbianca ah good call with the parser debugging. Since <code/>
is treated as a block level element, it will not parse the internal HTML. You can work around that even easier with:
innerHTML(document.getElementById('example2'), html, {
parser: {
// Disable <code /> being a block level element
rawElements: [ 'script', 'noscript', 'style', 'template' ] // or just use [] if you don't need these elements
}
});