Literal 0.6.2

Template scope

Literal templates are rendered in a scope that contains some useful objects and functions.

The data object is the data passed into the template to be rendered:

${ data.name }

Other templates can be included with include() function:

${ include('#some-other-template', data) }

Expressions that return promises or streams cause the DOM to be updated when values are resolved. The events() function, for example, returns a mappable stream of events:

${ events('hashchange', window).map((e) => location.hash) }

Some functions are simply built-ins, aliased for brevity (it is nicer to read ${ values(data) } than ${ Object.values(data) } within the constraints of a template).

Objects

data

The main object passed into the template carrying data. This object is special. When it mutates, the DOM re-renders.

this

The current renderer. Normally this should not be touched, and is provided for debugging.

body

An alias of document.body.

element

The element enclosing the current template tag.

host

Where this literal template renders the shadow DOM of a custom element, host refers to the custom element.

shadow

Where this literal template renders the shadow DOM of a custom element, shadow refers to the custom element’s shadow root.

nothing

A frozen array-like and stream-like object that contains no value.

Functions

assign(a, b, )

Alias of Object.assign().

by(fn, a, b)

For sorting arrays. Compares fn(a) against fn(b) and returns -1, 0 or 1. Partially applicable. To sort an array of objects by their ids:

array.sort(by(get('id')))

ceil(n)

Alias of Math.ceil().

clamp(min, max, n)

Clamps number n to the limits min to max. Values of n lower than min return min, and those higher than max return max.

clock(duration)

If duration is a number, returns a stream of DOM timestamps at duration seconds apart.

${ clock(1).map(floor) }

If duration is "frame", returns a stream of DOM timestamps of animation frames.

${ clock('frame').map((time) => time.toFixed(2)) }

delegate(map)

Takes an object map of functions keyed to selectors, and returns a function that handles event objects, delegating them to the first function whose selector matches the event target. Functions are passed the target node and the event object, plus any other arguments passed to the handler.

delegate({
    'button': (button, event) => {}
})

entries(object)

Alias of Object.entries().

equals(a, b)

Compares a and b for deep equality and returns true where they are equal, otherwise false.

events(type, node)

Returns a mappable stream of events heard on node.

${ events('click', element).map((e) => e.target.id) }

The first parameter may also be an object with a type property. If the object has a select property that is a CSS selector, events are delegated from matching targets:

${ events({ type: 'click', select: '[name="button"]' }, element)
   .map((e) => e.target.value) }

Other properties are passed to addEventListener options, for passive and capture phase event binding:

${ events({ type: 'scroll', passive: true, capture true }, window)
   .map((e) => window.scrollTop) }

Stopping an event stream removes event listeners. Streams returned from expressions are automatically stopped when their renderers are removed.

floor(n)

Alias of Math.floor().

get(path, object)

Gets the value of path in object, where path is a string in JS dot-notation. Where a path does not lead to a value, returns undefined:

${ get('path.to.value', data) }

Numbers are accepted as path components:

${ get('array.0', data) }

id(value)

Returns value.

include(src, data)

Includes a template identified by src, passing in an object to render in that template as data. In production it is recommended that src is a fragment identifier referring to the id of a template already in the DOM:

${ include('#another-template', data) }

The include function is partially applicable, making it easy to use for looping over an array to return an array of rendered templates:

${ data.array.map(include('#list-item')) }

keys(object)

Alias of Object.keys().

last(array)

Returns the last value in an array.

matches(selector, object)

For filtering and pattern matching. Returns true where all the properties of selector object are strictly equal to the same properties of object. Note that object may have more properties than selector.

const vegetarian = menu.filter(matches({ vegetable: true }));

noop()

Does nothing, returns undefined.

overload(fn, map)

For function overloading. Takes a fn that returns a string key, and a map object of functions stored against keys. Returns a function that calls the function at the key generated by calling fn() with all arguments.

Where a key is not in map but map contains the property 'default', that default function is called. Where there is no default function an error is thrown.

var handleEvent = overload((e) => e.type, {
    click:   (e) => {...},
    input:   (e) => {...},
    default: (e) => {...}
});

paramify(object)

Turns an object with enumerable properties into a native URL search parameters object. Rejects undefined properties and flattens out array values.

print(data)

Where window.DEBUG was falsy at the time Literal is imported, print() does nothing.

Prints an object or objects to the DOM as a debug message.

<template is="literal-template" data="../../package.json">
    ${ print(data) }
</template>

Renders as:

request(method, url)

Uses fetch() to send a request to url. Returns a promise.

${ request(method, url).then(...) }

To send data with the request:

${ request(method, url, data).then(...) }

Where type is "GET", data is serialised and appended to the URL, otherwise it is sent as a request body.

A 4th parameter may be a content type string or a headers object (in which case it must have a 'Content-Type' property).

${ request(method, url, data, headers).then(...) }

round(n, value)

Round value to the nearest multiple of n.

slugify(string)

Replaces any series of non-word characters with a '-' and lowercases the rest.

    slugify('Party on #mydudes!') // 'party-on-mydudes'

Stream.combine(object)

Creates a stream of objects containing the latest values of all streams and promises in object, as soon as they become active or resolved.

Stream.combine({ a: stream, b: promise }).each((object) => {
    // object.a and object.b are values
});

If object contains properties that are not streams or promises, those are also set on streamed objects.

Stream.combine({ a: stream, b: promise, c: 5 }).each((object) => {
    // object.c is 5
});

Output objects are created using the constructor of the input object, making it possible to use an array or other object as input and expect an array or other object as output.

Stream.combine([promise, stream]).each((object) => {
    // object is an Array
});

The stream may be made mutable by passing true (or an options object with mutable set to true) as a second parameter. In this case no new objects are constructed, instead the input object is mutated and pushed to the output stream. This may be a Good Idea when it is necessary to avoid garbage collection, such as when animating.

Stream.combine({ a: stream, b: promise }, true).each((object) => {
    // object is the input object, properties a and b are now values
});

Stream.from(source)

Creates a stream from source, which may be a pipeable (an object with .pipe() and .stop() methods), an array (or array-like), or a promise.

Stream.merge(stream1, stream2, )

Creates a stream by merging values from any number of input streams into a single output stream. Values are emitted in the time order they are received from inputs.

Stream.merge(stream1, stream2).each((value) => {
    // value is from stream1 or stream 2
});

Stream.of(value1, value2, )

Creates a pushable BufferStream from the given parameters.

sum(a, b)

Returns the sum of b + a.

translate(key)

Looks up an alternative value stored by key in a window.translations object, if it exists. A super simple translation mechanism, but requires window.translations to be populated.

${ translate('Go to homepage') }

trigger(type, node)

Triggers event of type on node. Returns false if the event default was prevented, otherwise true.

trigger('activate', node);

Alternatively the first argument may be an object with a type property, and optionally detail, which must be an object, and bubbles, cancelable and composed options, which determine the behaviour of the event.

trigger({
    type:       'activate',
    detail:     {...},
    bubbles:    true,
    cancelable: true,
    composed:   false
}, node);

values()

Alias of Object.values().

px(value)

Takes a number in pixels or a string of the form '10px', '10em', '10rem', '100vw', '100vh', '100vmin' or '100vmax', and returns a numeric value in pixels.

em(value)

Takes numeric value in px, or CSS length of the form '10px', and returns a numeric value in em, eg. 0.625. Depends on the user defined browser font-size.

rem(value)

Takes numeric value in px, or CSS length of the form '10px', and returns a numeric value in rem, eg. 0.625. Depends on the font-size of the documentElement.

vw(value)

Takes number in pixels or CSS length of the form '10em' and returns a numeric value in vw, eg. 120. Depends on the width of the viewport at render time.

vh(value)

Takes number in pixels or CSS length of the form '10em' and returns a numeric value in vh, eg. 120. Depends on the height of the viewport at render time.

Template expressions

How evaluated expressions are rendered into the DOM depends upon their type.

Promises are resolved before they render, arrays are flattened and joined without spaces or commas, and streams are re-rendered every time they emit a new value.

Literal flattens nested collections – a promise of a stream of arrays of strings will render as a string as its values arrive.

False-y values, other than false itself, don’t render at all, so expressions may evaluate to undefined or null and go unseen.

Type Expression Renders as
undefined ${ undefined }
null ${ null }
NaN ${ NaN }
String ${ 'Hello' }
Boolean ${ true }, ${ false }
Number ${ 100.3 }
Infinity ${ Infinity }, ${ -Infinity }
Function ${ function name(param) {} }
Arrow ${ (param) => {} }
RegExp ${ /^regexp/ }
Symbol ${ Symbol('name') }
Array ${ [0, 1, 2, 3] }
Object ${ { property: 'value' } }
Node ${ document.createTextNode('Text') }
Promise ${ Promise.resolve('promise') }
Stream ${ events('pointermove', body)
  .map((e) => e.pageX.toFixed(1)) }

Built by Stephen Band for Cruncher logo Cruncher.

Documentation set in Euclid and Martian Mono. Fonts used for documentation not included as part of the license covering the use of Literal.