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 🙏

© 2025 – Pkg Stats / Ryan Hefner

excise

v1.1.2

Published

a toolkit for writing functional-style (react-like) web components, based on [diffhtml](https://github.com/tbranyen/diffhtml)

Readme

excise

a toolkit for writing functional-style (react-like) web components, based on diffhtml

install

npm install excise

usage

basic

you'll need a browser that supports custom elements v1 and shadow dom v1. chrome 55 will work.

const {define, html} = require('excise');

define('x-hello-world', () => html`<h1>it works!</h1>`);

document.body.innerHTML = '<x-hello-world></x-hello-world>';

polyfills

the only polyfills i've found that work are custom-elements and shadydom. they're not fully on npm yet but they can be installed with:

npm install --save webcomponents/shadydom webcomponents/custom-elements

and then include them with

require('@webcomponents/shadydom');
require('@webcomponents/custom-elements');

or as entry points to your bundle

bundling

i've found it difficult to get this working with webpack because it thinks define means AMD and even if you disable that plugin it breaks. just use browserify, and don't bother with babel because we need to natively extend HTMLElement.

props

element attributes are passed as an object to the render function

const {define, html} = require('excise');

define('x-count', ({count}) => html`<h1>${count}</h1>`);

document.body.innerHTML = '<x-count count="5"></x-count>';

pass a third argument to define to specify the types of the props, for coercion:

const {define, html, types} = require('excise');

define('x-increment', ({count}) => html`<h1>${count + 1}</h1>`, {count: types.number});

document.body.innerHTML = '<x-increment count="5"></x-increment>';

server rendering

call renderToString with an html block:

const {define, html, renderToString} = require('excise');

define('x-foo', () => html`<h1>hello</h1>`);

renderToString(html`<x-foo></x-foo>`); //⇒ <x-foo><span slot="__excise_rendered"><h1>hello</h1></span></x-foo>

the extra span allows you to reuse the server-rendered markup on the client. when your elements are defined, the __excise_rendered slot is ignored.

events

on* attributes are attached to elements as event handlers:

const {define, html} = require('excise');

define('x-button', () => html`<button onclick=${() => alert('hello!')}>click me</button>`);

document.body.innerHTML = '<x-button></x-button>';

state

StatefulComponent watches its attributes and rerenders when they change:

const {StatefulComponent, html, types} = require('excise');

StatefulComponent.define('x-counter',
	(props, el) => html`<b>${props.count}</b> <button onclick=${() => el.setAttribute('count', props.count + 1)}>click me}</button>`,
	{count: types.number}
);

document.body.innerHTML = '<x-counter count="1"></x-counter>';

there's a little bit of oddness here. we can't destructure count here like in previous examples, because of how diffhtml renders the button. the actual dom of the button never changes (it's the same structure) so diffhtml leaves it alone when count updates. this means the onclick handler still closes over count from the first run of the render function, and the button only works once.

shadow dom/slots

const {define, html} = require('excise');

define('x-shadow', () => html`<slot name="title" /> <h2>slots work</h2>`);

document.body.innerHTML = '<x-shadow><h1 slot="title">it works!</h1></x-shadow>';

classes

const {Component, html, types} = require('excise');

define(class XClassComponent extends Component {
	static get propTypes() {
		return {
			greeting: types.string,
		};
	}

	render() {
		return html`<h1>it works! ${this.props.greeting}</h1>`;
	}
});

document.body.innerHTML = '<x-class-component greeting="hello!"></x-class-component>'

licence

ISC. © matt brennan