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

htmlefet

v1.0.1

Published

Minimalist, non-intrusive one way binding html library

Downloads

4

Readme

HTMLefet

HTMLefet helps you bind data to html in a fast, robust way - using web standards and no more!

(no build step required - looking at you, lit-html)

Basic usage:

<script type="module">
    import {efet} from "https://cdn.jsdelivr.net/npm/htmlefet/htmlefet.js"

    window.state = {
        name: "Inigo Montoystory",
        color: "red"
    };

    // Binding the above object to an html template
    let boundElement = eval(efet())(state, () => `
        <div>
            My name is <span style="color: ${state.color}">
                ${state.name}
            </span>
        </div>
    `);

    // boundElement is a regular html element!
    document.body.appendChild(boundElement);

    // modifying the state
    state.name = "John Cena!!!";
    setInterval(() => state.color = state.color === "blue" ? "red" : "blue", 300);
</script>

Play with it live: https://jsfiddle.net/8k1rvq6a/2/

In the above example, boundElement is a regular DOM element. The only thing that sets it apart is that when a property of state changes, the corresponding expression in the template will be re-evaluated and updated in the element's DOM.

To get a feel for it, you can open the devtools and play with the state object!

All of HTML, Bound

HTMLefet is straightforward - it's just html with js chunks inside. you don't have to learn how to use it. If your knowledge of js and html is a hand, HTMLefet is a well-fitting work glove.

Expressions

<div>my age will be ${state.age + 1} some day</div>

Events

<button onclick="${() => state.clicks += 1}">
    click me baby ${state.clicks} more time
</button>

CSS

<style>
 #thing {
    color: ${state.color};
 }
</style>
<div id="thing">colorful things</div>

You could write a css line (color: red;), or even a whole rule.

Attributes

<input placeholder=${state.placeholder}/>
<div ${state.hidden ? "hidden" : ""}></div>

Nested

let boundElement = eval(efet())(state, () => `
<div>
    ${state.amAlive ? "yes" : eval(efet())(innerState, () => `
        <span style="color: ${innerState.deathColor}">NO</span>
    `)}
</div>
`);

Notice how the inner template uses a different state object: innerState.

Loops

import {efet} from "https://cdn.jsdelivr.net/npm/htmlefet/htmlefet.js"

window.state = {
    friends: [{
        name: "dave",
        isNice: true
    }, {
        name: "Mojojojo",
        isNice: false
    }, {
        name: "harambe",
        isNice: true
    }]
};

let boundElement = eval(efet())(state, () => `
<div>
    ${state.friends.map(friend => eval(efet())(friend, () => `
        <div style="color: ${friend.isNice ? "green" : "red"};">
            ${friend.name}
        </div>
    `))}
</div>
`);

document.body.appendChild(boundElement);

state.friends[0].isNice = false; // Boom

WTF The Fuck? We returned an array of bound elements, each of which is bound to a different friend. When we changed the isNiceness of the first friend, its bound element changed automatically.

keyed logic coming soon...

Web Components

No web rendering library is complete without a showoff of it's intended usage, while comparing it to other frameworks and stating why it's better!

...Coming Soon...

But why?

You're probably thinking "another web rendering library, more garbage, grate success". There are dozens of great libraries claiming to do the same, written by pretty smart people. so what sets HTMLefet apart?

Expression Hooks

HTMLefet maintains two important mappings in the background:

  • properties to expression (state.age is linked to the expression ${state.age / 2 + 7})
  • expressions to DOM Nodes (${state.age / 2 + 7} is linked to the div <div>${state.age / 2 + 7}</div>)

When a property is changed (state.age += 1), it's corresponding expression is re-evaluated, and the result goes into the DOM Node.

It sounds simple, but it has a great advantage over other rendering libs: changes to the state follow with the minimum amount of reactions to make the DOM change.

Lets compare that to React

React claimed to be pretty fast because it took the slowest operation in the web and minimized it: changing the DOM. React keeps a copy of the DOM (called virtual dom), and whenever a rerender is queued, React compares the virtual DOM to the actual one, and changes the diffs.

But there's a problem. Imagine building a component that contains a huge list of all the words, ever. You'd think that you only have to pay once, performance wise: when rendering the list to the DOM. But it's not the case, because whenever you call setState without changing the list, the whole list is still going to be compared to the actual DOM, unless you move that to another component, forcing you to create lots of small and coupled components.

The comparison is not as heavy as actually replacing the DOM, but it's still very heavy when there's lots of stuff on the virtual DOM to compare.

That's one aspect where HTMLefet wins: when some property changes, instead of comparing the whole component, HTMLefet knows exactly what element to change because it holds a reference to it.

Level up: Lets compare to lit-html

TODO: Make sure im not bullshitting about how lit-html works...

Lit-html is the inspiration for this project (alongside lighterhtml). they keep it simple: no binding, user decides when to render. each rendering, the template is evaluated with all the expressions inside it, and puts them inside the DOM with the minimum amount of DOM work possible.

The catch: imagine a website showing two numbers: PI and E, but it calculates them on page load. on the fly

Disclaimer

All of what I said about the performance being good is a speculation, maybe i'm completely wrong - i havent run tests yet, soon i'll update with benchmark results.