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

(htm + vhtml) How do I insert unescaped HTML from variable? #137

Closed
dimgel opened this issue Dec 3, 2019 · 6 comments
Closed

(htm + vhtml) How do I insert unescaped HTML from variable? #137

dimgel opened this issue Dec 3, 2019 · 6 comments

Comments

@dimgel
Copy link

dimgel commented Dec 3, 2019

Hello. Trying hml-2.2.1 mini + vhtml-2.1.0 min. Below are few use cases I tried, which demonstrate totally inconsistent behaviour.

Case 1 (good but useless):

let h = "<p>hello</p>";
document.body.innerHTML = html`${h}`;
// wanted: <p>hello</p>
// got:    <p>hello</p>

Case 2: wrapping ${h} into <div> (real use case):

let h = "<p>hello</p>";
document.body.innerHTML = html`<div>${h}</div>`;
// wanted: <div><p>hello</p></div>
// got:    <div>&lt;p&gt;hello&lt;/p&gt;</div>

Case 3: manually calling html() with wrapping <div> (real use case):

let h = "<p>hello</p>";
return html`<div>${html(h)}</div>`;
// wanted: <div><p>hello</p></div>
// got:    <div>hello<undefined></undefined></div>

Case 3a (real example I initially stuck into; it looses <p> around "text"):

let h = "<main><h1>title</h1><p>text</p></main>";
return html`<div>${html(h)}</div>`;
// wanted: <div><main><h1>title</h1><p>text</p></main></div>
// got:    <div><main><h1>title</h1>text</main><undefined></undefined></div>

Case 4: manually calling html() without wrapping <div>:

let h = "<p>hello</p>";
return html`${html(h)}`;
// wanted: <p>hello</p>
// got:    ,,,h,,e,,l,,l,,o,,<undefined></undefined>

Case 5: manually calling html() with wrapping <div> and variable containing multiple elements:

let h = "<p>hello</p><p>world</p>";
return html`<div>${html(h)}</div>`;
// wanted: <div><p>hello</p><p>world</p></div>
// got:    <div>world<undefined></undefined></div>

I suppose I do it wrong in case 5, I should wrap multiple <p> into some single element, like I do in case 3a. I could also ignore weird <undefined> elements if it worked correctly otherwise.

So, how do I do it correctly, then?

Thanks.

@goranmoomin
Copy link

goranmoomin commented Dec 3, 2019

That's not htm's work, htm passes the arguments without escaping anything. What framework are you binding to?

When binding with vhtml, this:

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

const html = htm.bind(vhtml);

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

returns

<div><p>Hello, World!</p></div>

edit: Something was wrong (in my computer) and this is apparently not right.

@dimgel
Copy link
Author

dimgel commented Dec 3, 2019

No framework, I use htm.bind(vhtml) exactly as you've shown.

Example: http://dimgel.me/drop/vhtml/7-bug-undefined-tag.html
Result: http://dimgel.me/drop/vhtml/7-bug-undefined-tag.png

@dimgel
Copy link
Author

dimgel commented Dec 3, 2019

Re-uploaded files to show case 2 (previously mistakingly uploaded case 3).

Actually, I came to realize that just pure JS string interpolation would be enough for me, I only have to explicitly escape plain texts, like <h1>${esc(title)}</h1><div>${bodyHtml}</div>.

@goranmoomin
Copy link

Okay, maybe my computer was a little strange :-(

Template tag functions get arguments as arrays: so you might have more luck in calling html(['<p>Hello, World!</p>']).

This

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>`);

produces:

<div><p>Hello, World!</p></div>

codesandbox

@dimgel
Copy link
Author

dimgel commented Dec 3, 2019

That worked indeed, thank you! :)

@ooling
Copy link

ooling commented Sep 28, 2022

@goranmoomin
I noticed it only worked if the value only contain valid html, when I add an preact component it doesn't work, how to solve it?

Here's an example :

import {htm,h,MyComponent} from 'my/local/host/path/...';
let jsx = htm.bind(h);
console.log(
  jsx([
  `<div><${MyComponent}/></div>`
  ])
);

Result :
Screenshot_20220928-193911403

Anyway the screenshot above is taken from Spck Editor on Android.

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

No branches or pull requests

3 participants