/literal

Literal templates for the DOM

Primary LanguageHTML

Literal 0.8.3

Literal is a DOM-first templating library that enhances HTML <template>s with JS literal expressions and renders them with a data binding DOM renderer.

Quick start

<template is="literal-html">

A literal-html template is replaced in the DOM with its own rendered content. HTML <template>s are allowed pretty much anywhere in a document, so literal-html templates enable you to freely mix islands of dynamically rendered content into your HTML.

Import literal-html/module.js to start rendering literal-html templates:

<script type="module" src="./build/literal-html/module.js"></script>

Every Literal template has a data object. In this example the default export of clock.js is imported as data and its time property rendered:

<template is="literal-html" src="./build/data/clock.js">
    <p>${ data.time.toFixed(0) } seconds since page load.</p>
</template>

${ data.time.toFixed(0) } seconds since page load.

When no data is explicitly imported Literal renders the template with an empty data object. In this example data is not used, and the template renders a stream of pointer events:

<template is="literal-html">
    <p>${ events('pointermove', body).map((e) => round(e.pageX)) }px</p>
</template>

${ events('pointermove', body).map((e) => round(e.pageX)) }px

Templates can include() other templates. Here, data is imported from a JSON file and an array of tasks is mapped to a collection of <li>s:

<template id="li-template">
    <li>${ data.text }</li>
</template>

<template is="literal-html" src="./data/todo.json">
    <ul>${ data.tasks.map(include('#li-template')) }</ul>
</template>
  • ${ data.text }
    • ${ data.tasks.map(include('#li-template')) }

    <template is="literal-element">

    A literal-element template declares a custom element and defines its shadow DOM, allowing you to author custom elements entirely within HTML.

    Import literal-element/module.js to start rendering literal-element elements:

    <script type="module" src="./build/literal-element/module.js"></script>

    Here's a declaration of a bare-bones '<my-toggle>' element. It is recommended to put these in the <head>, but you don't have to.

    <template is="literal-element" tag="my-toggle" attributes="active:boolean">
        <button type="button">
            <!-- Render button text -->
            ${ data.active ? 'Hide' : 'Show' } slotted content
            <!-- Listen to events on the button -->
            ${ events('click', element).each(() => data.active = !data.active) }
        </button>
        <slot hidden="${ !data.active }"></slot>
    </template>

    The custom element can now be authored as:

    <my-toggle>
        <p>This paragraph is shown when my-toggle is active.</p>
    </my-toggle>
    ${ data.active ? 'Hide' : 'Show' } slotted content ${ events('click', element).each(() => data.active = !data.active) }

    This paragraph is shown when my-toggle is active.