npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rlighterhtml

v0.14.5

Published

The hyperHTML strength & experience without its complexity

Downloads

3

Readme

lighterhtml

donate Build Status WebReflection status License: ISC Greenkeeper badge Blazing Fast

The hyperHTML strength & experience without its complexity 🎉

faster than hyperHTML

Even if sharing 90% of hyperHTML's code, this utility removed all the not strictly necessary parts from it, including:

  • no Component, no define and/or intents, no connect or disconnect, and no promises (possibly in later on), everything these days can be easily handled by hooks, as example using the dom-augmentor utility
  • html content is never implicit, since all you have to do is to write html before any template when you need it. However, the {html: string} is still accepted for extreme cases.

Removing these parts made the output smaller in size (less than 6K) but it also simplified some underlying logic.

Accordingly, lighterhtml delivers raw domdiff and domtagger performance in an optimized way.

If you don't believe it, check the DBMonster benchmark 😉

simpler than lit-html

In lit-html, the html function tag is worthless, if used without its render.

In lighterhtml though, the html tag can be used in the wild to create any, one-off, real DOM, as shown in this pen.

// lighterhtml: import the `html` tag and use it right away
import {html} from '//unpkg.com/lighterhtml?module';

// a one off, safe, runtime list 👍
const list = ['some', '<b>nasty</b>', 'list'];
document.body.appendChild(html`
  <ul>${list.map(text => html`
    <li>${text}</li>
  `)}
  </ul>
`);

Strawberry on top, when the html or svg tag is used through lighterhtml render, it automatically creates all the keyed performance you'd expect from hyperHTML wires, without needing to manually address any reference: pain point? defeated! 🍾

"but ... how?", if you're asking, the answer is simple: lighterhtml is based on the same augmentor's hooks concept, followed by automatically addressed hyperhtml-wires, which in turns brings a battle tested solution for the O(ND) Eugene W. Myers' Algorithm based domdiff, and its extra variations.

Available as lighterhtml-plus too!

Born just as own fork of this project, lighterhtml-plus enhances the HTML5 experience through these extras:

  • onconnected callback, as in hyperHTML, to have Custom Elements like callbacks
  • ondisconnected callback, as in hyperHTML, to have counter events when nodes get disconnected
  • onattributechanged callback, as in wickedElements, to have attributes change notifications, Custom Elements like

How to import lighterhtml/-plus

Following, the usual multi import pattern behind every project of mine:

  • via global lighterhtml CDN utility: <script src="https://unpkg.com/lighterhtml"></script>, and const {render, html, svg} = lighterhtml
  • via ESM CDN module: import {render, html, svg} from 'https://unpkg.com/lighterhtml?module'
  • via ESM bundler: import {render, html, svg} from 'lighterhtml'
  • via CJS module: const {render, html, svg} = require('lighterhtml')

What's the API ? What's in the export ?

The module exports the following:

  • html tag function, create as one-off any sort of html content, or wired content when used within a render call
  • svg tag function, create as one-off any sort of SVG content, or wired content when used within a render call
  • render(node, fn) to pollute a node with whatever is returned from the fn parameters, including html or svg tagged layout, as well as any real DOM content, if needed
  • hook(useRef) that returns hooks compatible html and svg utilities, using a useRef(null) reference to provide a keyed updated per each component
  • Hole class for 3rd parts (internal use)

You can test live a hook example in this Code Pen.

What's different from hyperHTML ?

  • the wired content is not strongly referenced as it is for hyperHTML.wire(ref[, type:id]) unless you explicitly ask for it via html.for(ref[, id]) or svg.for(ref[, id]), where in both cases, the id doesn't need any colon to be unique, and it's the string default when not specified. This makes content hard wired whenever it's needed.
  • the ref=${object} attribute works same as React, you pass an object via const obj = useRef(null) and you'll have obj.current on any effect. If you'll pass {set current(node) { ... }} that'll be invoked per each update, in case you need the node outside useRef.
  • intents, hence define, are not implemented. Most tasks can be achieved via hooks.
  • promises are not in neither. You can update asynchronously anything via hooks or via custom element forced updates. Promises might be supported again in the future to align with isomorphic SSR, but right now these are not handled at all.
  • the onconnected and ondisconnected special events are gone. These might come back in the future but right now dom-augmentor replaces these via useEffect(callback, []). Please note the empty array as second argument.
  • an array of functions will be called automatically, like functions are already called when found in the wild
  • the Component can be easily replaced with hooks or automatic keyed renders
const {render, html} = lighterhtml;

// all it takes to have components with lighterhtml
const Comp = (name) => html`<p>Hello ${name}!</p>`;

// for demo purpose, check in console keyed updates
// meaning you won't see a single change per second
setInterval(
  greetings,
  1000,
  [
    'Arianna',
    'Luca',
    'Isa'
  ]
);

function greetings(users) {
  render(document.body, () => html`${users.map(Comp)}`);
}

Documentation

Excluding the already mentioned removed parts, everything else within the template literal works as described in hyperHTML documentation.

A basic example

Live on Code Pen.

import {render, html} from '//unpkg.com/lighterhtml?module';

document.body.appendChild(
  // as unkeyed one-off content, right away 🎉
  html`<strong>any</strong> one-off content!<div/>`
);

// as automatically rendered wired content 🤯
todo(document.body.lastChild);
function todo(node, items = []) {
  render(node, () => html`
  <ul>${items.map((what, i) => html`
    <li data-i=${i} onclick=${remove}> ${what} </li>
  `)}
    <button onclick=${add}> add </button>
  </ul>`);
  function add() {
    items.push(prompt('do'));
    todo(node, items);
  }
  function remove(e) {
    items.splice(e.currentTarget.dataset.i, 1);
    todo(node, items);
  }
}

What about Custom Elements ?

You got 'em, just bind render arguments once and update the element content whenever you feel like.

Compatible with the node itself, or its shadow root, either opened or closed.

const {render, html} = lighterhtml;

customElements.define('my-ce', class extends HTMLElement {
  constructor() {
    super();
    this.state = {yup: 0, nope: 0};
    this.render = render.bind(
      // used as update callback context
      this,
      // used as target node
      // it could either be the node itself
      // or its shadow root, even a closed one
      this.attachShadow({mode: 'closed'}),
      // the update callback
      this.render
    );
    // first render
    this.render();
  }
  render() {
    const {yup, nope} = this.state;
    return html`
    Isn't this <strong>awesome</strong>?
    <hr>
    <button data-key=yup onclick=${this}>yup ${yup}</button>
    <button data-key=nope onclick=${this}>nope ${nope}</button>`;
  }
  handleEvent(event) {
    this[`on${event.type}`](event);
  }
  onclick(event) {
    event.preventDefault();
    const {key} = event.currentTarget.dataset;
    this.state[key]++;
    this.render();
  }
});

Should I ditch hyperHTML ?

Born at the beginning of 2017, hyperHTML matured so much that no crucial bugs have appeared for a very long time.

It has also been used in production to deliver HyperHTMLElement components to ~100M users, or to show W3C specifications, so that in case of bugs, hyperHTML will most likely be on the fast lane for bug fixes, and lighterhtml will eventually follow, whenever it's needed.

On top of this, all modules used in lighterhtml are part of hyperHTML core, and the ./tagger.js file is mostly a copy and paste of the hyperHTML ./objects/Update.js one.

However, as tech and software evolve, I wanted to see if squashing together everything I know about template literals, thanks to hyperHTML development, and everything I've recently learned about hooks, could've been merged together to deliver the easiest way ever to declare any non-virtual DOM view on the Web.

And this is what lighterhtml is about, an attempt to simplify to the extreme the .bind(...) and .wire(...) concept of hyperHTML, through a package that requires pretty much zero knowledge about those internals.

lighterhtml is also relatively new, so that some disabled functionality might come back, or slightly change, but if you like the idea, and you have tested it works for your project, feel free to ditch hyperHTML in favor of lighterhtml, so that you can help maturing this project too.