developit / htm

Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot insert literal HTML because & is always escaped

paulinemss opened this issue · comments

Hi,

An issue came up with HTML content that we receive from the server. We want to insert it into htm without escaping it. According to #137, we should be able to do as follows:

import htm from "htm";
import vhtml from "vhtml";

const html = htm.bind(vhtml);

const frag = "<p>Hello, World!</p>"
console.log(html`<div>${html([frag])}</div>`);   // output: "<div><p>Hello, World!</p></div>"

However, this doesn't work with HTML special characters - see example below (and in CodeSandbox).
It looks like html([]) is still escaping & to &amp;, which breaks other special chars.

import htm from "htm";
import vhtml from "vhtml";

const html = htm.bind(vhtml);

const frag = "<p>Hello &lt; World</p>"           // "Hello < World"
console.log(html`<div>${html([frag])}</div>`);   // output: "<div><p>Hello &amp;lt; World</p></div>"

Could this be a bug? Or is above not the intended use case for inserting literal HTML? Is this perhaps not supported at all?

As an example use case, we might be getting highlighted search results (I &lt;3 <em>htm</em>) from the trusted server, which we want to insert into a htm template without escaping.

See example in CodeSandbox

Hi @paulinemss!

This is a vhtml thing fwiw, not HTM. That said, you're close to the right solution! html() doesn't support bypassing sanitization of nested calls (I don't recall the reason). It does support the dangerouslySetInnerHTML prop similar to React though, which does what you're looking for:

const frag = "<p>We &lt;3 <em>htm</em></p>";

const rendered = html`<div dangerouslySetInnerHTML=${{ __html: frag }}></div>`;

Thanks a lot @developit!