Skip to main content
Version: 2.x

Composition

The key of micro-lc flexibility lies – among others – in the built-in capacity of transforming a string or a serialization markup language content, as JSON or YAML, into a valid, appendable DOM.

This behaviour enables the possibility to dynamically instruct micro-lc on the shape of a page by writing a configuration file to be loaded at runtime, and can be applied both on layout and content when using compose integration strategy.

Let us take a look at a working example. The frame below shows a simple use case where the page is divided into layout and content and both are constructed dynamically from a textual configuration.

How it works

tip

The composition functionality is exposed though micro-lc composer API.

At height level, this feature is achieved by leveraging lit-html library APIs combined with a lexer and a non-eval interpolation library.

info

One of the main feature of micro-lc composition is, actually, that it does not exploit any kind of unsafe runtime evaluation (e.g., eval or Function) which are strongly discouraged on websites and mitigated via omission in Content-Security-Policy.

Almost any HTML element can be seen, from the point of view of the DOM, as the combination of:

  • a tag (e.g., <div>, <header>, <aside>, <img>, <micro-lc>),
  • a list of attributes (e.g., style="margin: 10px;", class="my-css-class"),
  • a list of boolean attributes (e.g., hidden, disabled),
  • a list of properties injected by JavaScript on the DOM counterpart of the given element,
  • a content inside of the tag, (e.g., 0, Hello, World!, <p>My Paragraph</p>).
HTML element
<p  Tag
id="my-awesome-paragraph" Attribute
disabled Boolean attribute
>
Hello, World! ⬅ Content
</p>

<script>
const element = document.getElementById('my-awesome-paragraph')
element.className = 'my-custom-dynamic-class'Property
</script>

HTML elements can be full represented in JavaScript with the help of lit-html ES6 tagged templates, that evaluate attributes, boolean attributes and properties. The example above would translate in:

Lit HTML element rappresentation
import {html} from 'lit-html'

const customClassName = 'my-custom-dynamic-class'

const template = html`
<p Tag
id="my-awesome-paragraph" Attribute
disabled="" Boolean attribute
.className=${customClassName} Property
>
Hello, World! ⬅ Content
</p>
`

Now that the desired HTML tree is described in JavaScript, a render function attaches the template to a provided container (i.e., another HTML element) by interpreting non-dotted keys (e.g, id, disabled) as attributes, and dotted keys (e.g., className) as JavaScript properties.

tip

In micro-lc composition api, properties can be any combination of numbers, strings, arrays or JSON equivalent objects.

Before doing this, however, we need to address the fact that we do not know the value of customClassName at compile time, and we would like to inject it at runtime (without using eval, of course!). To solve this issue, micro-lc provides a lexer and an interpolation API to plug a fully compliant template literal to the lit-html library.

Together, these tools make the composition API, the flow of which is fully visualized in the example below.

The complete process

Let us consider the following JSON file describing what we would like out DOM to be.

JSON DOM description
{
"tag": "div",
"attributes": {
"style": "margin: 10px;"
},
"content": [
{
"tag": "p",
"content": "Some Text"
},
{
"tag": "button",
"booleanAttributes": ["disabled"],
"properties": {
"myProp": { "foo": "bar" },
"special": "special.[0]"
},
"content": "Click Me!"
}
]
}