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

hyperglue2

v3.2.0

Published

A hyperglue implementation

Downloads

18

Readme

hyperglue2

A hyperglue implementation (DOM-only).

npm

Why

Hyperglue is an awesome templating engine that accepts vanilla html strings or DOM elements as templates. This is nice because you don't have to learn any fancy new languages and you can update templates you've already rendered without recompiling any HTML.

Although the concept behind this library is faithful to the original, the API is not. More about this under Notes.

How

Set textContent

var hg = require('hyperglue2');
var el = hg('<div></div>', 'hello');
// or 
var el = hg('<div></div>', { _text: 'hello' });
// <div>hello</div>

Make updates

// note: 'el' is a dom element, not a string
hg(el, 'hello world');
// <div>hello world</div>

InnerHTML

hg(el, { _html: '<input>' });
// <div><input></div>

Attributes

hg(el, { input: { _attr: { name: 'field', value: 42 }}}); // add
// <div><input name="field" value="42"></div>
hg(el, { input: { _attr: { name: null }}});               // remove
// <div><input value="42"></div>

Form element value (attributes only work for inital values)

hg(el, { input: { _value: 23 }});              // add
// <div><input value="42"></div>               // but display and js will show 23
hg(el, { input: { _value: null }});            // remove
// <div><input value="42"></div>               // but display and js will show ""

Generic properties

hg(el, { input: { _prop: { checked: true }}}); // sets .checked directly on element

ClassList

hg(el, { input: { _class: { hidden: true }}}); // add
// <div><input class="my-input hidden"></div>
hg(el, { input: { _class: { hidden: false }}}); // remove
// <div><input class="my-input"></div>

Elements

var el = hg('<div></div>');
var header = hg('<h1></h1>');
var bold = hg('<b>elementary</b>');

hg(el, header);                     // element literal
hg(el, { h1: { _element: bold }});  // element selector
// <div><h1><b>elementary</b></h1></div>

Singletons

var src = 'movie.avi'
var opts = {
  video: {
    _single: src,
    _attr: {
      src: src
    }
  }
}
var el = hg('<div><video></video></div>', opts);
// <div><video src="movie.avi"></video></div>
el.querySelector('video').setAttribute('data-single', '')
el = hg('<div><video></video></div>', opts);
// <div><video src="movie.avi" data-single></video></div>

Arrays

var el = hg('<ul><li></li></ul>', { li: [ 1, 2, 3 ] });
// <ul>
//   <li>1</li>
//   <li>2</li>
//   <li>3</li>
// </ul>

Array updates

hg(el, { li: [ 1, 'the end' ] });
// <ul>
//   <li>1</li>
//   <li>the end</li>
// </ul>

Respect element boundaries

hg('<section><h1></h1><section><h1></h1></section></section>', { h1: 'the title' }, { boundary: 'section' });
// <section>
//   <h1>the title</h1>
//   <section>
//     <h1></h1>
//   </section>
// </section>

Notes

So, I really like the original hyperglue library, but!

  • the ":first" selector confused me
  • array updates don't work
  • can't remove attributes

Detailed explanations below:

The ":first" selector

The first thing you're likely to try with hyperglue is probably something along the lines of: hg('<div></div>', 'hello world') which of course doesn't work, because to select outer elements you actually need to use the ":first" selector like so: hg('<div></div>', { ':first': 'hello world' }). Hyperglue2 does away with ":first" and just assumes you are always talking about the outermost element you've selected, this sacrifices attribute manipulation ease in favor of a more obvious way to set inner content:

// original hyperglue
hg('<ul><li></li></ul>', { li: [ { ':first': 1 }, { ':first': 2 }, { ':first': 3 } ] });
// <ul>
//   <li>1</li>
//   <li>2</li>
//   <li>3</li>
// </ul>

// hyperglue2
hg('<ul><li></li></ul>', { li: [ 1, 2, 3 ] });
// <ul>
//   <li>1</li>
//   <li>2</li>
//   <li>3</li>
// </ul>

Array updates

Updating an existing dom element (instead of generating a new one from a string) is possible with the original hyperglue, but it doesn't work for arrays. Consider:

// original hyperglue

// first render
var el = hg('<ul><li></li></ul>', { li: [ { ':first': 1 }, { ':first': 2 }, { ':first': 3 } ] });

// update
hg(el, { li: [ { ':first': 'a' }, { ':first': 'b' }, { ':first': 'c' } ] });
// <ul>
//   <li>a</li>
//   <li>b</li>
//   <li>c</li>
//   <li>a</li>
//   <li>b</li>
//   <li>c</li>
//   <li>a</li>
//   <li>b</li>
//   <li>c</li>
// </ul>

// Works in hyperglue2
var el = hg('<ul><li></li></ul>', { li: [ 1, 2, 3 ] })
hg(el, { li: [ 'a', 'b', 'c' ] });
// <ul>
//   <li>a</li>
//   <li>b</li>
//   <li>c</li>
// </ul>

Attribute removal

Some html attributes like "checked" or "selected" can't be set to falsy values, so the only way to disable them is to completely remove the attribute. You can remove attributes with hyperglue2 by setting the attribute data value to null.

hg('<input type="checkbox" checked>', { _attr: { checked: null }});
// <input type="checkbox">

Releases

The latest stable release is published to npm. Below is an abbreviated changelog:

  • 3.x

    • Switch to MIT license.
  • 2.x

    • Explictly passing null values now removes elements matched by the given selector. Clearing textContent can be done by passing an empty string.
  • 1.6.x

    • Add _value selector for working with form inputs (value attribute and textContent only work for setting an initial value)
  • 1.5.x

    • Don't use for-in loop as it doesn't work properly on arrays with unset indexes
  • 1.4.x

    • Add classList support via the _class selector
  • 1.3.x

    • Improved falsy value handling
  • 1.1.x

    • Added _element selector
  • 1.0.x

    • Added ability to pass DOM elements as data
    • Added "boundary" option
  • 0.0.x

    • Prototype

License

MIT