Go to file
Talia c5c4e973a5 Remove valueKey from StoredState 2024-01-17 14:09:50 +01:00
domLense.js Refactor exports 2024-01-11 15:44:11 +01:00
license.md Update metadata 2023-10-04 10:35:56 +02:00
package.json Add subscribe method to state class 2024-01-17 11:39:16 +01:00
readme.md Move description above import block in readme 2023-12-23 18:25:05 +01:00
skooma.js Make `handle` return a value just in case it is desired 2024-01-15 11:50:27 +01:00
state.js Remove valueKey from StoredState 2024-01-17 14:09:50 +01:00



A functional-friendly helper library for procedural DOM generation and templating.

import {html} from "skooma.js"


const text = new State({value: "Skooma is cool"})
setTimeout(() => {text.value = "Skooma is awesome!"}, 1e5)

    html.h1("Hello, World!"),
    html.p(text, {class: "amazing"}),
    html.button("Show Proof", {click: event => { alert("It's true!") }})

Interface / Examples

Basic DOM generation

Accessing the html proxy with any string key returns a new node generator function:

html.div("Hello, World!")

Attributes can be set by passing objects to the generator:

html.div("Big Text", {style: "font-size: 1.4em"})

Complex structures can easily achieved by nesting generator functions:

        html.b("Bold Text")

For convenience, arrays assigned as attributes will be joined with spaces:

html.a({class: ["button", "important"]})

Assigning a function as an attribute will instead attach it as an event listener:

html.button("Click me!", {click: event => {
    alert("You clicked the button.")

Generators can be called with many arguments. Arrays get iterated recursively as if they were part of a flat argument list.

Generating Text Nodes

text("Hello, World")
// Wraps document.createTextNode
// Defaults to empty string instead of erroring
// Non-string arguments still error

text`Hello, World!`
// returns a new document fragment containing the text node "Hello, World!"
text`Hello, ${user}!`
// returns a document fragment containing 3 nodes:
// "Hello, ", the interpolated value of `user` and "!"
text`Hello, ${html.b(user)}!`
// Text node for Hello, the <b> tag with the user's name, and a text node for !


import {handle} from 'skooma.js'

Since it is common for event handlers to call preventDefault(), skooma provides a helper function called handle with the following definition:

fn => event => { event.preventDefault(); return fn(event) }

A few more examples:

Create a Button that deletes itself:

	html.button("Delete Me", {click: event => event.target.remove()})

Turn a two-dimensional array into an HTML table:

const table = rows =>
		row => html.tr(row.map(
			cell => html.rd(cell, {dataset: {
				content: cell.toLowerCase(),

A list that you can add items to

let list, input = ""
	html.input({type: 'text', input: e => input = e.target.value}),
	html.button({click: event => list.append(html.li(input))}, "Add"),

A list that you can also delete items from

const listItem = content => html.li(
	html.span(content), " ", html.a("[remove]", {
		click: event => event.target.closest("li").remove(),
		style: { cursor: 'pointer', color: 'red' },
let list, input = ""
	html.input({type: 'text', input: e => input = e.target.value}),
	html.button({click: event => list.append(listItem(input))}, "Add"),