3.4 KiB
Interpolation
In Loom, interpolation refers to the process of modifying text values in an abstract syntax tree (AST) by applying data held in scope in code to the strings.
The mechanism provided by loom for these interpolations are the
interpolate*()
functions:
interpolate: tree, node, string, value, object, array
interpolateNode(...)
- Interpolate a single nodeinterpolateArray(...)
- Interpolate an array's valuesinterpolateObject(...)
- Interpolate an object's propertiesinterpolateString(...)
- interpolate a stringinterpolateTree(...)
- interpolate an ASTinterpolateValue(...)
- interpolate a value of unknown type
Interpolation data
The most simple interface to interpolation is using a context mask. See that section for more details.
Context
As you traverse a tree or subtree of nodes, you can assign data to the node
for later interpolation. This data is called the node's context. Each
node's context is stored in its .data.context
property. Note that the
Unified.js AST convention provides the .data
property and other things may
modify its contents. Use .data.context
for a safe place to store the
node's data for interpolation purposes.
When a node is processed, it gets sees the context of all of its parents. Nearer contexts shadow farther contexts. This works in the same way that shadowing works in JavaScript, where the innermost value is used. In JavaScript, this is seen this way:
(foo) => {
let a = 1;
[10,20].forEach((a) => console.log(a));
console.log(a);
}
Notice that inside the interior function, the parent's value of a
is
shadowed by the child's value of a
from the function's signature. This
script will output:
10
20
1
In a loom AST, the functionality is very similar. Consider the following HTML AST (abbreviated for clarity):
{
"tagName": "personal-greetings",
data: { context: { name: "Othello" } },
"children": [
{
"tagName": "p",
"children": [
{ type: "text", value: "Hello, ${name}!" }
]
},
{
"tagName": "p",
data: { context: { name: "Margaret" } },
"children": [
{ type: "text", value: "Hello, ${name}!" }
]
},
]
}
Notice that the <personal-greetings> tag has context associated with it:
.data.context.nameis set to
"Othello"`.
Of the two children, the former item does not have its own data, while the
latter item does; it's context sets the name
to "Margaret"
.
The code to interpolate and render the AST could look like this:
console.log(astToHtml(interpolate(tree)));
The rendered version of this AST to HTML would look like this:
<personal-greetings>
<p>Hello, Othello!</p>
<p>Hello, Margaret!</p>
</personal-greetings>
In the first node, name
is available through the parent's context. In the
second node, name
is shadowed by the child's own value, "Margaret".
Context Masks
You may interpolate any value with a context mask by passing it in as a
second parameter to the interpolate\*()
functions.
Using the example provided in the Contexts section, you could write:
console.log(astToHtml(interpolate(tree, {name: "Samwise"})));
The rendered version of this AST to HTML would look like this:
<personal-greetings>
<p>Hello, Samwise!</p>
<p>Hello, Samwise!</p>
</personal-greetings>