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

noml

v1.0.10

Published

NOML

Readme

NOML (no markup language)

Let's admit it, HTML and Javascript really suck for making applications. They have separate purposes (UI and logic) with no real glue to bind them. Enter jQuery, Backbone, Ember, Angular, React, the list goes on and on. All of these improve the glue, but still rely on some complicated mapping model between the HTML and Javascript.

With NOML there is no HTML (or JSX, or Xml-ish-ness). NOML renders javascript objects into html. This technique allows for dynamic content to be rendered on the fly, modified, and bound with logic, without ever touching HTML. The entire application is written in literal, readable, unconverted Javascript. The glue is solved (chemistry pun intended).

see working examples at https://github.com/adamduffy/noml-examples

Simple examples

results when noml.render() is called on the object.

ui.span('hello world!');
<span>hello world!</span>

child elements

ui.div(
	ui.span('span 1'),
	ui.span('span 2')
)
<div><span>span 1</span><span>span 2</span></div>

properties

NOML Element classes have a prop method.

ui.span('welcome to noml').prop({id: 'mySpanId'})
<span id="mySpanId">welcome to noml</span>

variables

since this is javascript to begin with, variables work naturally

var data = {name: 'adam'};
ui.span('my name is ' + data.name)
<span>my name is adam</span>

class handling

ui.span('a classy span').class('myClass')
<span class='myClass'>a classy span</span>

the NOML Element class handles de-duping of class names.

ui.span('a very classy span')
	.class('myClass1 myClass3')
	.class('myClass1 myClass2')
	.class('myClass3');
<span class='myClass1 myClass2 myClass3'>a very classy span</span>

Class names can be added, removed, or conditional, even after the initial render. All props can be re-synced with the dom using .ref() at creation, and .syncProps() to update.

  • class adds a class
  • unclass removes a class
  • classIf adds the class if condition is true, removes if false.
  • toggle swaps the class based on condition.
  • all classname methods perform de-duping.
const span = ui.span('a re-classed span')
	.class('myClass1 myClass2')
	.classIf(true, 'conditionalClass')
	.toggle(true, 'trueClass', 'falseClass')
	.ref(); // .ref() tells noml to keep a reference.
// render the span
render(span);
// at this point, className='myClass1 myClass2 conditionalClass trueClass'
span.unclass('myClass2')
	.classIf(false, 'conditionalClass')
	.toggle(false, 'trueClass', 'falseClass')
	.syncProps(); // this will re-sync with the dom.
// now, className='myClass1 falseClass'
<span id="_0" class='myClass1'>a re-classed span</span>

events

NOML will wire to DOM events during render. the Element class wraps a few common events

ui.span('click here').onClick(() => alert('hi!'));

or you can use any other event name

ui.span('mouse enter here').event({mouseenter: () => alert('mouse entered!')})

###components Noml will render modular ui elements as components that allow for special interaction such as independent re-rendering and promise resolution. to do this, expose a getBody() method.

TODO: make example

you can give the component your own id or noml will auto-assign one so it can reference it for re-rendering, etc.

if your code maintains a reference to this object, the ui can be refreshed later by calling c.render() or c.syncProps(). this technique is best for low-level components where you want immediate response. For most cases, just re-rendering the whole page is much easier to manage. (and should still be very snappy)

###Asynchronous component loading

to make loading, ready, and failure states, simply return a promise from getBody and expose a getLoadingBody() method. noml will re-render the ui when the promise is resolved or fails.

...
	getBody() {
		return Promise.resolve(span('this is a resolved promise'));
	},
	getLoadingBody() {
		return span('loading');
	}
...

'loading' will render until the promise is resolved.

<component id="_0"><span>this is a resolved promise</span></component>

###Reading input data

To keep the abstraction away from html, the best way to read user input is by mapping it back to your javascript data objects. You can do this with the change or other similar element events. Noml will wire up native dom element events if you begin a property with $. Another option is to give the element a unique id and find it later.

TODO: make example

##Styles

Noml also uses javascript to define CSS (optional). The general format is as follows:

{
	id: {
		class: {
			property: value,
			state: {
				property: value, ...
			}, ...
		}, ...
	}, ...
}

Noml uses c.id and c.getStyle() to maintain the composite css object. Class names can be prepended with $ in place of . when desired (other selectors work in place of class name). Included examples show techniques to define and override default styles.


	getDefaultStyle() {
    return {
      $clickable: {
        cursor: 'pointer',
        ':hover': {
					'text-decoration': 'underline'
        }
      }
    };
  }
#page .clickable {
	cursor:pointer;
}
#page .clickable:hover {
	text-decoration:underline;
}

##Putting it all together

That is the extent of the Noml library itself. This leaves a lot of room for project architecture around it. Here is a basic example of how to begin:

start with a simple html file:

<!DOCTYPE html>
<html>
<head>
	<script type="text/javascript" src="readme.js"></script>
	<title>Noml example</title>
</head>
	<body>
	</body>
</html>

and a simple js file:

import {renderPage, ui} from 'noml';

window.onload = bodyOnLoad();

function bodyOnLoad() {
	renderPage(ui.span("my first noml app"));
}

The included example shows a technique of structuring an application with ui, data, logic, and state all managed.