Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A brief features comparison between hyperHTML and lit-html
hyperHTML lit-html
released March 2017 August 2017
version 2.5.0 0.7.1
license ISC BSD 3-Clause License
compatibility template literals Edge 13+, FF 34+, CH 41+, SF 9.1+, iOS 9.2+ Edge, FF 55+, CH 41+, SF 9.1+, iOS 9.2+
compatibility transpiled IE9+ FF 34+, WK (Android 4+), CH, SF, iOS 8+ template literals only IE11/Edge, FF 55+, CH (CH for Android), SF 9+, iOS 9+ library and template literals
tests Build Status Coverage Status Build Status
size 4.8k brotli - transpiled and usable as script 2.2k unbundled ESM + extended 1.6k + repeat 1.6k
code style ES2015 Module
bundled/compatible with ESM, CJS and ES3
TypeScript / ES2015 Module
not pre bundled
⚡️ BASIC FEATURES
production ready 🔎
no transpilers 🔎
no polyfills 🔎
self closing tags 🔎
smart parser: once per template literal 🔎
secure text by default 🔎
composable 🔎
extensible 🔎
asynchronous 🔎
components 🔎
⚡️ ATTRIBUTES
smart attributes 🔎
smart style attribute 🔎
regular attributes 🔎
boolean attributes 🔎 ⚠️
special attributes 🔎 ⚠️
events attributes 🔎 ⚠️
attribute w/out quotes 🔎
partial attributes 🔎
⚡️ CONTENT
smart diffing 🔎
smart content 🔎
reliable content 🔎
html content 🔎
nested content 🔎
repeated content 🔎 ℹ️
SVG 🔎
partial Table 🔎
temporary content 🔎
conditional content 🔎
weakly referenced content 🔎
adoptable content 🔎 ℹ️
⚡️ EXTRAS
Custom Elements HyperHTMLElement Polymer 3
SSR viperHTML
Native nativeHTML
BE DOM Compatibility basicHTML, jsdom
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

How To Contribute: in case of changes or updates, please leave a comment. I will update related raw and delete the comment after.

hyperHTML examples might use a html tag like function. While it's not exposed by default, you can have easily create one.

const html = (...args) => hyperHTML.wire()(...args);

Thank you


P.S. haters and fanboys will be ignored/canceled/banned

Owner

WebReflection commented Aug 23, 2017

How To Contribute: in case of changes or updates, please leave a comment. I will update related raw and delete the comment after.

hyperHTML examples might use a html tag like function. While it's not exposed by default, you can have easily create one.

const html = (...args) => hyperHTML.wire()(...args);

Thank you


P.S. haters and fanboys will be ignored/canceled/banned

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

smart parser

In both hyperHTML and lit-html using twice the same template literals will not parse, traverse, and create updates more than once.

// first usage will traverse the DOM
html`<div>${'hello'}</div>`;
// second time, even if interpolated content is different
// the DOM will be simply cloned / imported from a <template>
html`<div>${'there'}</div>`;
Owner

WebReflection commented Aug 23, 2017

smart parser

In both hyperHTML and lit-html using twice the same template literals will not parse, traverse, and create updates more than once.

// first usage will traverse the DOM
html`<div>${'hello'}</div>`;
// second time, even if interpolated content is different
// the DOM will be simply cloned / imported from a <template>
html`<div>${'there'}</div>`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

secure

In both hyperHTML and lit-html passing interpolations as string, number, or boolean, will result in textContent value.

// results: "<p>&lt;b&gt;nope&lt;/b&gt;</p>"
html`<p>${'<b>nope</b>'}</p>`;

// results: "<p>123</p>"
html`<p>${123}</p>`;

// results: "<p>false</p>"
html`<p>${false}</p>`;
Owner

WebReflection commented Aug 23, 2017

secure

In both hyperHTML and lit-html passing interpolations as string, number, or boolean, will result in textContent value.

// results: "<p>&lt;b&gt;nope&lt;/b&gt;</p>"
html`<p>${'<b>nope</b>'}</p>`;

// results: "<p>123</p>"
html`<p>${123}</p>`;

// results: "<p>false</p>"
html`<p>${false}</p>`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

composable


hyperHTML

You can compose hyperHTML templates through DOM nodes, wired nodes, and you can append directly single nodes to the DOM.

document.body.appendChild(
  html`<p>${'yup, this works'}</p>`
);

// or even ...
hyperHTML.bind(document.body)`
  ${document.querySelector('h1')}
  <ul>
    ${[1, 2, 3].map(num => `<li>${num}</li>`)}
  </ul>
`;

For a list of all supported values, see the documentation.


lit-html

In lit-html you can compose with lit-html objects only.

const header = html`<h1>${title}</h1>`;
const render = () => html`
  ${header}
  <p>And the body</p>
`;
Owner

WebReflection commented Aug 23, 2017

composable


hyperHTML

You can compose hyperHTML templates through DOM nodes, wired nodes, and you can append directly single nodes to the DOM.

document.body.appendChild(
  html`<p>${'yup, this works'}</p>`
);

// or even ...
hyperHTML.bind(document.body)`
  ${document.querySelector('h1')}
  <ul>
    ${[1, 2, 3].map(num => `<li>${num}</li>`)}
  </ul>
`;

For a list of all supported values, see the documentation.


lit-html

In lit-html you can compose with lit-html objects only.

const header = html`<h1>${title}</h1>`;
const render = () => html`
  ${header}
  <p>And the body</p>
`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

extensible


hyperHTML

You can define your own behavior directly as new intent.

// extend behaviors
hyperHTML.define('sha256', (interpolation) => {
  // you can return any hyperHTML compatible value, including Promises
  return fetch('/sha256?value=' + encodeURIComponent(interpolation))
              .then(b => b.text());
});

// use it whenever you need
hyperHTML.wire()`
<p>
  Your sha256 secret is ${{sha256: user.secret}}
</p>`;

This makes hyperHTML templates automatically portable and/or testable in isolation, plus it grants the ability to change, or update, at any time the intended behavior.

You can read more in the documentation.


lit-html

You can extend through directives.

html`<div>${directive((part) => { part.setValue('Hello')})}</div>`

Directives are functions that receive an internal Part object with some method you can use to update the interpolated value.

To have a named directive you can assign it once and reuse later on.

const safe = (f) => directive((part) => {
  try {
    return f();
  } catch (e) {
    console.error(e);
  }
});

let data;
const render = () => html`foo = ${safe(_=>data.foo)}`;
Owner

WebReflection commented Aug 23, 2017

extensible


hyperHTML

You can define your own behavior directly as new intent.

// extend behaviors
hyperHTML.define('sha256', (interpolation) => {
  // you can return any hyperHTML compatible value, including Promises
  return fetch('/sha256?value=' + encodeURIComponent(interpolation))
              .then(b => b.text());
});

// use it whenever you need
hyperHTML.wire()`
<p>
  Your sha256 secret is ${{sha256: user.secret}}
</p>`;

This makes hyperHTML templates automatically portable and/or testable in isolation, plus it grants the ability to change, or update, at any time the intended behavior.

You can read more in the documentation.


lit-html

You can extend through directives.

html`<div>${directive((part) => { part.setValue('Hello')})}</div>`

Directives are functions that receive an internal Part object with some method you can use to update the interpolated value.

To have a named directive you can assign it once and reuse later on.

const safe = (f) => directive((part) => {
  try {
    return f();
  } catch (e) {
    console.error(e);
  }
});

let data;
const render = () => html`foo = ${safe(_=>data.foo)}`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

asynchronous


hyperHTML

You can use a Promise as interpolation value or an explicit intent with an optional placeholder.

// basic asynchronous
hyperHTML.bind(document.body)`
  The response is ${fetch('sample.txt').then((r) => r.text())}.
`;

// fetch the list and render it as HTML
html`<ul>
  ${{
    html: fetch('/grocery').then(b => b.text())
    placeholder: 'Loading list ...'
  }}
</ul>`;

// or wire some content
html`<ul>
  ${{
    any: fetch('/grocery.json')
          .then(b => b.json())
          .then(list => list.map(
            item => hyperHTML.wire()
            `<li data-id=${item.id}>${item.name}</li>`
          ))
    placeholder: spinner.cloneNode(true)
  }}
</ul>`;

A placeholder can be any value accepted already by hyperHTML, including DOM nodes.


lit-html

You can use a Promise as interpolation value or you can use an until(promise, defaultContent) utility.

// basic asynchronous
const render = () => html`
  The response is ${fetch('sample.txt').then((r) => r.text())}.
`;

// until utility
const render = () => html`
  <p>
    ${until(
        fetch('content.txt').then((r) => r.text()),
        html`<span>Loading...</span>`)}
  </p>
`;

The default content should be a valid value for a part.setValue(defaultContent) operation.

Owner

WebReflection commented Aug 23, 2017

asynchronous


hyperHTML

You can use a Promise as interpolation value or an explicit intent with an optional placeholder.

// basic asynchronous
hyperHTML.bind(document.body)`
  The response is ${fetch('sample.txt').then((r) => r.text())}.
`;

// fetch the list and render it as HTML
html`<ul>
  ${{
    html: fetch('/grocery').then(b => b.text())
    placeholder: 'Loading list ...'
  }}
</ul>`;

// or wire some content
html`<ul>
  ${{
    any: fetch('/grocery.json')
          .then(b => b.json())
          .then(list => list.map(
            item => hyperHTML.wire()
            `<li data-id=${item.id}>${item.name}</li>`
          ))
    placeholder: spinner.cloneNode(true)
  }}
</ul>`;

A placeholder can be any value accepted already by hyperHTML, including DOM nodes.


lit-html

You can use a Promise as interpolation value or you can use an until(promise, defaultContent) utility.

// basic asynchronous
const render = () => html`
  The response is ${fetch('sample.txt').then((r) => r.text())}.
`;

// until utility
const render = () => html`
  <p>
    ${until(
        fetch('content.txt').then((r) => r.text()),
        html`<span>Loading...</span>`)}
  </p>
`;

The default content should be a valid value for a part.setValue(defaultContent) operation.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

smart attributes

Whenever an attribute value is changed, hyperHTML will not assign it if identical to the previous one.

This makes it impossible to have backfiring infinite-loops on Custom Elements attributes changes and also it avoids input issues in browsers like WebKit and others when setting twice, as example, input.value = 'text' will make the cursor lose focus.

Currently, lit-html is backfiring prone in non Chrome environments + it will lose focus on WebKit when using the extended version.

// simply try to move the cursor around in Safari
// every 2 seconds it'll go back to the end
setInterval(
  () => render(html`<input value=${'text'}>`, document.body),
  2000
);
Owner

WebReflection commented Aug 23, 2017

smart attributes

Whenever an attribute value is changed, hyperHTML will not assign it if identical to the previous one.

This makes it impossible to have backfiring infinite-loops on Custom Elements attributes changes and also it avoids input issues in browsers like WebKit and others when setting twice, as example, input.value = 'text' will make the cursor lose focus.

Currently, lit-html is backfiring prone in non Chrome environments + it will lose focus on WebKit when using the extended version.

// simply try to move the cursor around in Safari
// every 2 seconds it'll go back to the end
setInterval(
  () => render(html`<input value=${'text'}>`, document.body),
  2000
);
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

regular attributes

Both hyperHTML and lit-html supports setting any regular attribute by default.

// all good
html`<p class=${'ok'} data-value=${'ok'}></p>`;
Owner

WebReflection commented Aug 23, 2017

regular attributes

Both hyperHTML and lit-html supports setting any regular attribute by default.

// all good
html`<p class=${'ok'} data-value=${'ok'}></p>`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

boolean attributes

While hyperHTML supports boolean attributes by default, you need to be careful with lit-html because by default, attributes are simply set via node,setAttribute(name, valueAsString).

This leads to unexpected results.

// the result in base lit-html would be
// <button disabled="false">click?</button>
// keeping the button actually disabled
html`<button disabled=${false}>click?</button>`;

To avoid this issue you need to use the extended version of the library.

Owner

WebReflection commented Aug 23, 2017

boolean attributes

While hyperHTML supports boolean attributes by default, you need to be careful with lit-html because by default, attributes are simply set via node,setAttribute(name, valueAsString).

This leads to unexpected results.

// the result in base lit-html would be
// <button disabled="false">click?</button>
// keeping the button actually disabled
html`<button disabled=${false}>click?</button>`;

To avoid this issue you need to use the extended version of the library.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

special attributes

While hyperHTML supports special attributes by default, you need to be careful with lit-html because by default, attributes are simply set via node,setAttribute(name, valueAsString).

This leads to unexpected results.

html`<input value=${'before'}>`;

// now type something in the input

// now notice nothing actually changes in the layout
html`<input value=${'after'}>`;

To avoid this issue you need to use the extended version of the library.

Owner

WebReflection commented Aug 23, 2017

special attributes

While hyperHTML supports special attributes by default, you need to be careful with lit-html because by default, attributes are simply set via node,setAttribute(name, valueAsString).

This leads to unexpected results.

html`<input value=${'before'}>`;

// now type something in the input

// now notice nothing actually changes in the layout
html`<input value=${'after'}>`;

To avoid this issue you need to use the extended version of the library.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

events attributes


hyperHTML

You can simply pass either a callback or an object that implements the EventListener interface.

Every native and custom event is supported, as long as its prefix is on.

hyperHTML.bind(document.body)`
  <a href=${site} onclick=${e => e.preventDefault()}>
    click and nothing happens
  </a>
`;

You can add any event and remove it simply passing null. The template owner will be the event owner and all events are simply an indirection to a node.addEventListener(type, handler, false) or node.removeEventListener(type, handler, false) invokes.

This makes the node reliable, listeners speaking, in case node.onclick = fn happens in user-land or third parts libraries.


lit-html

By default, lit-html is not compatible with events. You need to use the extended version of the library or you will have unexpected results.

html`
  <a href="#" onclick=${e => e.preventDefault()}>
    click and nothing happens
  </a>
`;
// it will literally create the node with a string listener
// this is NOT what you want, this is not what you should do!
<a href="#" onclick="e => e.preventDefault()">

Once you use the extended version of the library you will have the following constrains:

  • events must be prefixed with on- ... so that <a on-click=${ok}> but the natural <a onclick=${fail}> will badly disappoint.
  • events must be functions only, even if the library internally uses handleEvent because it's just better. No idea why would they do that.
Owner

WebReflection commented Aug 23, 2017

events attributes


hyperHTML

You can simply pass either a callback or an object that implements the EventListener interface.

Every native and custom event is supported, as long as its prefix is on.

hyperHTML.bind(document.body)`
  <a href=${site} onclick=${e => e.preventDefault()}>
    click and nothing happens
  </a>
`;

You can add any event and remove it simply passing null. The template owner will be the event owner and all events are simply an indirection to a node.addEventListener(type, handler, false) or node.removeEventListener(type, handler, false) invokes.

This makes the node reliable, listeners speaking, in case node.onclick = fn happens in user-land or third parts libraries.


lit-html

By default, lit-html is not compatible with events. You need to use the extended version of the library or you will have unexpected results.

html`
  <a href="#" onclick=${e => e.preventDefault()}>
    click and nothing happens
  </a>
`;
// it will literally create the node with a string listener
// this is NOT what you want, this is not what you should do!
<a href="#" onclick="e => e.preventDefault()">

Once you use the extended version of the library you will have the following constrains:

  • events must be prefixed with on- ... so that <a on-click=${ok}> but the natural <a onclick=${fail}> will badly disappoint.
  • events must be functions only, even if the library internally uses handleEvent because it's just better. No idea why would they do that.
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

attribute w/out quotes


hyperHTML

In hyperHTML v1 you can set attributes without quotes but you cannot set partial attributes (considered YAGNI)

html`
  <p attr=${1} other=${2 + ' ' + 3}></p>
  <!-- or -->
  <p attr=${1} other=${[2, 3].join(' ')}></p>
  <!-- or -->
  <p attr=${1} other=${`${2} ${3}`}></p>
`;

lit-html

In lit-html you don't need quotes neither, and you can use above patterns.

However, if you want partial attributes you need to use quotes.

html`
  <p attr=${1} other="${2} ${3}"></p>
`;
Owner

WebReflection commented Aug 23, 2017

attribute w/out quotes


hyperHTML

In hyperHTML v1 you can set attributes without quotes but you cannot set partial attributes (considered YAGNI)

html`
  <p attr=${1} other=${2 + ' ' + 3}></p>
  <!-- or -->
  <p attr=${1} other=${[2, 3].join(' ')}></p>
  <!-- or -->
  <p attr=${1} other=${`${2} ${3}`}></p>
`;

lit-html

In lit-html you don't need quotes neither, and you can use above patterns.

However, if you want partial attributes you need to use quotes.

html`
  <p attr=${1} other="${2} ${3}"></p>
`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

partial attributes

For performance and semantic reasons, partial attributes are not supported in hyperHTML.

When an attribute changes, it cannot change partially. That's not how the DOM works, but you can obtain the same result with many available alternatives.

html`<divclass=${`foo ${mayBar ? 'bar' : ''}`}>Foo bar?</div>`;
html`<div class=${'foo' + (mayBar ? ' bar' : '')}>Foo bar?</div>`;
html`<div class=${['foo', mayBar ? 'bar' : ''].join(' ')}>Foo bar?</div>`;
html`<div style=${`top:${top}; left:${left};`}>x</div>`;

It's under consideration to simplify attribute creations through Array and an implicit .join(' ') which is the most common use case.

Owner

WebReflection commented Aug 23, 2017

partial attributes

For performance and semantic reasons, partial attributes are not supported in hyperHTML.

When an attribute changes, it cannot change partially. That's not how the DOM works, but you can obtain the same result with many available alternatives.

html`<divclass=${`foo ${mayBar ? 'bar' : ''}`}>Foo bar?</div>`;
html`<div class=${'foo' + (mayBar ? ' bar' : '')}>Foo bar?</div>`;
html`<div class=${['foo', mayBar ? 'bar' : ''].join(' ')}>Foo bar?</div>`;
html`<div style=${`top:${top}; left:${left};`}>x</div>`;

It's under consideration to simplify attribute creations through Array and an implicit .join(' ') which is the most common use case.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

smart content

Both hyperHTML and lit-html prevents useless repaint with same primitive values as content.

Owner

WebReflection commented Aug 23, 2017

smart content

Both hyperHTML and lit-html prevents useless repaint with same primitive values as content.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

reliable content

both hyperHTML and lit-html don't easily suffer collisions with the parsed content.

Owner

WebReflection commented Aug 23, 2017

reliable content

both hyperHTML and lit-html don't easily suffer collisions with the parsed content.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

html content


hyperHTML

You can explicitly opt-in for HTML in hyperHTML either passing an array or an {html: ...} intent.

// simple case, just an array of LIs strings
// injected as these are, nothing special, no parsing happens
hyperHTML.bind(document.body)`
<ul>
  ${items.map(item => `<li>${item.name}</li>`)}
</ul>`;

// explicit intent
hyperHTML.bind(document.body)`
<p>
  ${{
    html: fetch(content).then(b => b.text()),
    placeholder: 'Loading content ...'
  }}
</p>`;

It is also always possible to explicitly force text content, no matter what's passed along.

// explicit text intent
hyperHTML.bind(document.body)`
<p>
  ${{text: ['<strong>no way</strong>']}}
</p>`;

lit-html

You can pass any lit-html object as explicit html intent or you can use the unsafeHTML(anyHTML) directive.

Owner

WebReflection commented Aug 23, 2017

html content


hyperHTML

You can explicitly opt-in for HTML in hyperHTML either passing an array or an {html: ...} intent.

// simple case, just an array of LIs strings
// injected as these are, nothing special, no parsing happens
hyperHTML.bind(document.body)`
<ul>
  ${items.map(item => `<li>${item.name}</li>`)}
</ul>`;

// explicit intent
hyperHTML.bind(document.body)`
<p>
  ${{
    html: fetch(content).then(b => b.text()),
    placeholder: 'Loading content ...'
  }}
</p>`;

It is also always possible to explicitly force text content, no matter what's passed along.

// explicit text intent
hyperHTML.bind(document.body)`
<p>
  ${{text: ['<strong>no way</strong>']}}
</p>`;

lit-html

You can pass any lit-html object as explicit html intent or you can use the unsafeHTML(anyHTML) directive.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

nested content

Both hyperHTML and lit-html supports nested content as partial, asynchronous, object, or text.

Owner

WebReflection commented Aug 23, 2017

nested content

Both hyperHTML and lit-html supports nested content as partial, asynchronous, object, or text.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

repeated content


hyperHTML

In hyperHTML you just use JavaScript as you know it.

To repeat content use an Array#map(...) and return eventually wired objects.

const {bind, wire} = hyperHTML;

bind(document.body)`
<ul>
  ${items.map((i, index) =>
  wire(i)`<li>${index}: ${i.name}</li>`)}
</ul>`;

lit-html

You need to use a repeat(items, keyfn, template) utility, as explained in the documentation, if you want to reuse previously rendered nodes, otherwise it will create new DOM nodes each time.

const render = () => html`
  <ul>
    ${repeat(items, (i) => i.id, (i, index) => html`
      <li>${index}: ${i.name}</li>`)}
  </ul>
`;
Owner

WebReflection commented Aug 23, 2017

repeated content


hyperHTML

In hyperHTML you just use JavaScript as you know it.

To repeat content use an Array#map(...) and return eventually wired objects.

const {bind, wire} = hyperHTML;

bind(document.body)`
<ul>
  ${items.map((i, index) =>
  wire(i)`<li>${index}: ${i.name}</li>`)}
</ul>`;

lit-html

You need to use a repeat(items, keyfn, template) utility, as explained in the documentation, if you want to reuse previously rendered nodes, otherwise it will create new DOM nodes each time.

const render = () => html`
  <ul>
    ${repeat(items, (i) => i.id, (i, index) => html`
      <li>${index}: ${i.name}</li>`)}
  </ul>
`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

SVG

both hyperHTML and lit-html have a way to support SVG

Owner

WebReflection commented Aug 23, 2017

SVG

both hyperHTML and lit-html have a way to support SVG

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

partial Table

With both hyperHTML and lit-html You can create partial tables, raws, or cells.

const {bind, wire} = hyperHTML;

bind(document.body)`
<table>
  ${[[1, 2], [3, 4]].map(tr =>
  wire(tr)`<tr>
    ${tr.map(text => wire()`<td>${text}</td>`)}
  </tr>`)}
</table>`;

The result will be

<table>
  <tr>
    <td>1</td>
    <td>2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>4</td>
  </tr>
</table>
Owner

WebReflection commented Aug 23, 2017

partial Table

With both hyperHTML and lit-html You can create partial tables, raws, or cells.

const {bind, wire} = hyperHTML;

bind(document.body)`
<table>
  ${[[1, 2], [3, 4]].map(tr =>
  wire(tr)`<tr>
    ${tr.map(text => wire()`<td>${text}</td>`)}
  </tr>`)}
</table>`;

The result will be

<table>
  <tr>
    <td>1</td>
    <td>2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>4</td>
  </tr>
</table>
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

temporary content

As shown in the asynchronous related comment, both hyperHTML and lit-html can have a placeholder until some promise is resolved.

Owner

WebReflection commented Aug 23, 2017

temporary content

As shown in the asynchronous related comment, both hyperHTML and lit-html can have a placeholder until some promise is resolved.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

conditional content


hyperHTML

By default, hyperHTML supports homogeneous Arrays (same kind of content through the whole list).
It is therefore straightforward to have conditional content through ternary operators and/or Array#concat() composition.

html`<p>
  ${user.loggedIn ?
    `Welcome ${user.name}` :
    `You need to log-in`
  }
</p>`;

lit-html

While you can use ternary in lit-html too, their documentation shows future plans to implement a when(cond, then, else) utility.

const render = () => html`
  ${when(state === 'loading',
    html`<div>Loading...</div>`,
    html`<p>${message}</p>`)}
`;

However, currently it's not there and it's also not clear to me how that's supposed to work (passing an already checked condition instead of a function that returns true/false).

I will update this comment once it's clear what's the plan and how it works.

Owner

WebReflection commented Aug 23, 2017

conditional content


hyperHTML

By default, hyperHTML supports homogeneous Arrays (same kind of content through the whole list).
It is therefore straightforward to have conditional content through ternary operators and/or Array#concat() composition.

html`<p>
  ${user.loggedIn ?
    `Welcome ${user.name}` :
    `You need to log-in`
  }
</p>`;

lit-html

While you can use ternary in lit-html too, their documentation shows future plans to implement a when(cond, then, else) utility.

const render = () => html`
  ${when(state === 'loading',
    html`<div>Loading...</div>`,
    html`<p>${message}</p>`)}
`;

However, currently it's not there and it's also not clear to me how that's supposed to work (passing an already checked condition instead of a function that returns true/false).

I will update this comment once it's clear what's the plan and how it works.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

weakly referenced content

In hyperHTML you can use the same object as weak reference to generate once related templates, as explained in the documentation.


In lit-html the ownership of the current template is delegated to the parentNode and there's no mechanism to have the same content moved in two different places through an object and, optionally, an id.

Owner

WebReflection commented Aug 23, 2017

weakly referenced content

In hyperHTML you can use the same object as weak reference to generate once related templates, as explained in the documentation.


In lit-html the ownership of the current template is delegated to the parentNode and there's no mechanism to have the same content moved in two different places through an object and, optionally, an id.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 23, 2017

adoptable content

In hyperHTML V1 you could reuse the exact same template used in the backend, i.e. via viperHTML, and pickup its content instead of replacing it.

This experimental feature aim was to bring graceful enhancement to the next level, so that while a user is filling it a form, hyperHTML can kick in at any time without replacing what's already on the DOM.

In hyperHTML V2 this feature has been dropped bu it has been improved, and hidden, in viperHTML.
The next minor release will bring back a non experimental, 100% reliable, adopt feature.


In lit-html there's nothing like this and AFAIK it's also not planned.

Owner

WebReflection commented Aug 23, 2017

adoptable content

In hyperHTML V1 you could reuse the exact same template used in the backend, i.e. via viperHTML, and pickup its content instead of replacing it.

This experimental feature aim was to bring graceful enhancement to the next level, so that while a user is filling it a form, hyperHTML can kick in at any time without replacing what's already on the DOM.

In hyperHTML V2 this feature has been dropped bu it has been improved, and hidden, in viperHTML.
The next minor release will bring back a non experimental, 100% reliable, adopt feature.


In lit-html there's nothing like this and AFAIK it's also not planned.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Aug 31, 2017

components

Beside Custom Elements, hyperHTML ships with a basic hyper.Component class usable to define regular HTML container with ease and some little utility such connected and disconnected events.

Owner

WebReflection commented Aug 31, 2017

components

Beside Custom Elements, hyperHTML ships with a basic hyper.Component class usable to define regular HTML container with ease and some little utility such connected and disconnected events.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Sep 6, 2017

works without transpilers

hyperHTML can be used out of the box on IE9+ and mobile browsers without requiring any tooling.

That means that you can include the library via CDN and use it right away with the rest of your code you might, or might not, have transpiled already.

If you'd like to fully avoid transpilers and support IE you can: https://gist.github.com/WebReflection/9e79afe2ac808b0d726c7ed37b476fdc


lit-html currently needs browsers compatible with ES2015 modules or tools to be consumed by all its target browsers.

That means that lit-html is compatible without tooling with Chrome 61+ or Safari 10.1+. Edge and Firefox might need to enable a flag. Other target browsers work only if you used tooling.

Owner

WebReflection commented Sep 6, 2017

works without transpilers

hyperHTML can be used out of the box on IE9+ and mobile browsers without requiring any tooling.

That means that you can include the library via CDN and use it right away with the rest of your code you might, or might not, have transpiled already.

If you'd like to fully avoid transpilers and support IE you can: https://gist.github.com/WebReflection/9e79afe2ac808b0d726c7ed37b476fdc


lit-html currently needs browsers compatible with ES2015 modules or tools to be consumed by all its target browsers.

That means that lit-html is compatible without tooling with Chrome 61+ or Safari 10.1+. Edge and Firefox might need to enable a flag. Other target browsers work only if you used tooling.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Nov 15, 2017

works without polyfills

hyperHTML does not need any third parts polyfill and provides all fallbacks for outdated, non standard browsers, in core.

Owner

WebReflection commented Nov 15, 2017

works without polyfills

hyperHTML does not need any third parts polyfill and provides all fallbacks for outdated, non standard browsers, in core.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Nov 15, 2017

smart style attribute

With hyperHTML you can set style attributes in a way fully compatible with Preact.

hyper()`<p style=${{width: 100}}></p>`;
Owner

WebReflection commented Nov 15, 2017

smart style attribute

With hyperHTML you can set style attributes in a way fully compatible with Preact.

hyper()`<p style=${{width: 100}}></p>`;
@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Nov 15, 2017

smart diffing

With hyperHTML updates are performed through the domdiff library in order to mutate the least amount of nodes while reordering list1 to become list2.


In lit-html there is no logic behind list updates (yet?)

Owner

WebReflection commented Nov 15, 2017

smart diffing

With hyperHTML updates are performed through the domdiff library in order to mutate the least amount of nodes while reordering list1 to become list2.


In lit-html there is no logic behind list updates (yet?)

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Nov 16, 2017

production ready

hyperHTML is already being used by various developers for various projects and it demonstrated stability and performance over the last year.


lit-html still states on its README:

lit-html is very new, under initial development, and not production-ready.

Owner

WebReflection commented Nov 16, 2017

production ready

hyperHTML is already being used by various developers for various projects and it demonstrated stability and performance over the last year.


lit-html still states on its README:

lit-html is very new, under initial development, and not production-ready.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection Jan 19, 2018

self closing tags

hyperHTML understands self closing tags such <custom-element/> or even <i class="icon" />, making its writing competitive VS JSX.


lit-html does not understand self closing custom elements or non void tags.

Owner

WebReflection commented Jan 19, 2018

self closing tags

hyperHTML understands self closing tags such <custom-element/> or even <i class="icon" />, making its writing competitive VS JSX.


lit-html does not understand self closing custom elements or non void tags.

@FluorescentHallucinogen

This comment has been minimized.

Show comment
Hide comment
@tomByrer

This comment has been minimized.

Show comment
Hide comment
@tomByrer

tomByrer Apr 9, 2018

lit-html is now v0.9.0. I don't see any changes that would impact your chart.

tomByrer commented Apr 9, 2018

lit-html is now v0.9.0. I don't see any changes that would impact your chart.

@WebReflection

This comment has been minimized.

Show comment
Hide comment
@WebReflection

WebReflection May 11, 2018

hyperHTML is 2.12.0 too, but I have not much time to update this and if nobody tells me what to update I wouldn't care less.

Owner

WebReflection commented May 11, 2018

hyperHTML is 2.12.0 too, but I have not much time to update this and if nobody tells me what to update I wouldn't care less.

@ExE-Boss

This comment has been minimized.

Show comment
Hide comment
@ExE-Boss

ExE-Boss Jun 29, 2018

@WebReflection I have a PR ready at https://gist.github.com/ExE-Boss/ca044a52821b8ae46a6e75ccc851a302 (you can choose to only merge ExE-Boss/hyper-vs-lit-html.md@b315248 if you don’t want to use Shields.io for version reporting)

To merge it, you’ll need to clone and merge the Gist locally and then push it using git.

ExE-Boss commented Jun 29, 2018

@WebReflection I have a PR ready at https://gist.github.com/ExE-Boss/ca044a52821b8ae46a6e75ccc851a302 (you can choose to only merge ExE-Boss/hyper-vs-lit-html.md@b315248 if you don’t want to use Shields.io for version reporting)

To merge it, you’ll need to clone and merge the Gist locally and then push it using git.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment