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 🙏

© 2026 – Pkg Stats / Ryan Hefner

mithril-template

v0.0.1

Published

html to mithril hyperscript transpiler

Readme

Instalation

npm i -D mithril-template

Usage

var mithrilTemplate = require("mithril-template")

console.log(mithrilTemplate('<h1 class="greetings">Hello World</h1>'))

Template syntax- guide

Interpolation

The most basic form of data binding is text interpolation using the “Mustache” syntax (double curly braces):

<div class="greeting">
    Hello {{ name }}!
</div>

that will output:

m(".greeting","Hello "+name+"!")

Awesome, right? So let's dive deeper.

Interpolations can't be used within html tag definiition (also in attributes), so this code is invalid:

<div key="{{ foo }}" class="bar">
    Hello World!
</div>

instead use a binding attribute:

<div :key="foo" class="bar">
    Hello World!
</div>

output:

m(".bar",{key:foo},"Hello World!")

Note that { and } characters are reserved in templates for interpolation, so if you have to write them use this workaround:

<span>This is how to use {{ "{" }} and {{ "}"+"}" }} chars.</span>

You can't use &#123; and &#125; html entities because mithril will escape them

Eembeding components

To embed component, his name must end on -component, be kebab-case (a.k.a. snake-case) that will be automatically converted to camelCase and can't be self-closed tag:

<custom-component></custom-component>

output:

m(customComponent)

Attributes that are not followed by : (colon) will be ommited.

<custom-component class="custom-class"></custom-component>

output:

m(customComponent)

so if you want to pass data into component use binding syntax instead:

<custom-component :class="'custom-class'"></custom-component>

output:

m(customComponent,{class:'custom-class'})

You can nest anything inside the component:

<custom-component :key="'unique420'">
  <span style="color: red;">Hello!</span>
</custom-component>

output:

m(customComponent,{key:'unique420'},m("span[style='color: red;']","Hello!"))

Nested data will be available in vnode.children component view property:

<!--customComponent view-->
<div class="styled-message">{{ vnode.children[0] }}</div>

output:

m(".styled-message",vnode.children[0])

Binding attributes

You probably noticed that html attributes are compiled to hardcoded selectors:

<input type="text" name="name" value="name">

output:

m("input[type=text][name=name][value=name]")

if you want to bind html attribute just put : (colon) before attribute name:

<input type="text" name="name" :value="name">

output:

m("input[type=text][name=name]",{value:name})

you can also bind events and lifecycle hooks:

<div :oninit="initialize" :onclick="doSomething">
  Hello World!
</div>

output:

m("div",{oninit:initialize,onclick:doSomething},"Hello World!")

Directives

Directives are putted as html attributes that are previxed by * (asterisk). The result hyperscript code will be surrounded by javascript flow statements.

There are four available directives, that can be mixed togheder:

  • for
  • if
  • elseif
  • else

Let's explain, but note that examples' outputs below are unminified, for better readability.

if:

usage:

<div class="foo" *if="varr % 2 == 0">
  odd
</div>

output:

varr % 2 == 0
    ? m(".foo","odd")
    : ""

if-elseif && if-else:

<div class="foo" *if="varr % 2 == 0">
  odd
</div>
<div *elseif="varr % 5 == 0">
  divisible by 5
</div>
<div *else>
  other
</div>

output:

[
    varr % 2 == 0
        ? m(".foo","odd")
        : varr % 5 == 0
            ? m("div","divisible by 5")
            : m("div","other")
]

for:

<ul>
  <li *for="item in items">
    {{ item.name }}
  </li>
</ul>

output:

m("ul", items.map(function(n){
    return m("li", n.name)
}))

for with index:

<ul>
  <li *for="item, index in items">
    #{{ index }}: {{ item.name }}
  </li>
</ul>

output:

m("ul", items.map(function(n, a){
    return m("li","#"+a+": "+n.name)
}))

for-else

for loop can be used with else (or elseif) statement:

<ul>
  <li *for="item, index in items">
    #{{ index }}: {{ item.name }}
  </li>
  <li *else>
    items not found
  </li>
</ul>

output:

m("ul", items.length
    ? items.map(function(n, t){
        return m("li","#"+t+": "+n.name)
    })
    : m("li","items not found")
)

so if items array is empty (loop won't execute even once) then else statement will be executed

Traps

To maximally compress output- whitespaces whose belongs to tags are not properly handled, so if you write this code:

foo <span>bar</span> baz qux

the transpiled code will be:

["foo",m("span","bar"),"baz qux"]

instead of:

["foo ",m("span","bar")," baz qux"]

that you may expected. So if you need space between text and tag do it by this workaround:

foo{{ " " }}<span>bar</span>{{ " " }}baz qux

Additional advantages

  • properly support splats for better minification
  • produce maximally minified js code (also minify literal selectors)