WebReflection / lighterhtml

The hyperHTML strength & experience without its complexity 🎉
https://medium.com/@WebReflection/lit-html-vs-hyperhtml-vs-lighterhtml-c084abfe1285
ISC License
735 stars 20 forks source link

Expected Behavior of html.node? #95

Closed anywhichway closed 4 years ago

anywhichway commented 4 years ago

The second expression generating a body will work, the first produces the body as plain text. Is this expected?

I do understand that we could just put the template in the code, but we have cases where the templates are maintained externally.

 <body>
      <template id="main">
     <div>My HTML</div>
      </template>
    <script>
        //const body = lighterhtml.html.node`${document.getElementById("main").innerHTML}`;
        const body = Function("return lighterhtml.html.node`" + document.getElementById("main").innerHTML +"`")();
        document.body.appendChild(body);
    </script>
</body>

BTW, I had not revisited hyperHTML in about 18 months. Extraordinary improvements with ease of use for lighterhtml! Nice work!

WebReflection commented 4 years ago

glad you like improvements over here, and about your use case, you can try a different approach:

const main = document.getElementById("main").innerHTML;
render(document.body, html([main]));

would that work?

WebReflection commented 4 years ago

P.S. to clarify, you are simulating a template literal array with a unique content that doesn't need interpolated values: no Function/eval, you use primitives like ... primitives.

The only extra note is that a template is unique, when it's literal, while an array is always new, when passed that way.

Make your <template> code unique, as in cached once, and you have full functionality!

anywhichway commented 4 years ago

@WebReflection The alternate approach would work. I am just trying to understand expected behavior. And, yes in the current example there is no interpolation. However, we have plenty on templates that do require interpolation.

BTW, given the simplifications you have made, so long as we can get things working we plan to cease using our own engine 'hcx', a successor to 'tlx' which was a successor to 'fete'. I just filed an issue with 'uhtml' related to data binding. Our major use case is a whole bunch of html templates that contain a lot of data interpolation, but very little code. When there is code, it is typically a simple for loop. In some cases we have entire pages that are just one big data interpolation. We get the document body after load and simply re-render it bound to a data object (don't even bother to use a template tag, just replace what is there). This is because we have designers with little or no programming skill. One of the things that drives me bananas about React, Vue, Svelte is the amount of coding skill required.

WebReflection commented 4 years ago

will read this through, but this project came to my mind: https://github.com/WebReflection/backtick-template

if you can use eval/Function, it gives you proper interpolations as strings

anywhichway commented 4 years ago

@WebReflection This works!

<body onload="render(document.body,html([document.body.innerHTML]))">
<div>Test</div>
 </body>

Now if we could just do something like:

<body onload="render(document.body,html([document.body.innerHTML],{username:'joe'))">
<div>${username}</div>
</body>
WebReflection commented 4 years ago

So, the expected behavior is that by default you can't inject HTML, 'cause it's safe.

The html([content]) is a hack that does nothing special, it uses the html tag function simulating the template array it would receive if used as tag.

html`<p></p>`;
// similar to
html(['<p></p>'])

Bear in mind the template literal tag is unique, hence cached, never parsed more than once, while the array isn't, unless you cache it.

Again, this is a workaround, but in lighterhtml you could as well simply use {html: content} as interpolated value.

If you want to re-create the whole behavior of a tag you need:

None of this will ever land in here but this project gives you hints how to parse a string in search of ${holes}, how to create chunks and values, and how to evaluate: https://github.com/WebReflection/backtick-template/blob/master/index.js

As summary: there is no bug, everything is expected, but I won't land anything that needs Function/eval in here, as creating tag arguments from a string can be a project a part, nothing strictly related to this library.

I hope I've answered all your questions 👋

WebReflection commented 4 years ago

@anywhichway I've created the module that does that transformation, you can use it with your templates https://github.com/WebReflection/tag-params#readme 👋

anywhichway commented 4 years ago

@WebReflection Thanks ... and here we have what we need, named after what it must use.

html.with = (template,data) => html(...tagParams(template,data));

WebReflection commented 4 years ago

@anywhichway apologies for the change in v1, but it was for good. Please read the new exported API, as it covers much more now, and it's way more usable/useful.

The TL;DR is that you import {params} from 'tag-params' now, instead of directly the utility.

anywhichway commented 4 years ago

@WebReflection no problem!