Template JSON
Command: template-json
Description: Apply a Liquid template to JSON data to generate HTML. The entire working data is injected as an object in a variable called 'data'.
Arguments
-
template: Liquid template string -
url: URL to fetch template from -
selector: CSS selector to get template from DOM
Notes
Templating is via LiquidJS. The JSON will be injected as an object named data.
Assuming a JSON object like this:
{
"name": {
"first": "Deane",
"last": "Barker"
},
"age": 54
}
We can template like this:
template-json -template:$template
$template
<strong>Name:</strong> {{ data.name.last }}, {{ data.name.first }}
<br/>
<strong>Age:</strong> {% if data.age > 50 %}Old{% else %}Not Quite Old{% endif %}
The above example passes in the template directly as an argument, but there are two other options for getting the template string.
From an external URL, via HTTP:
template-json -url:http://my.web.site/template.liquid
Or from the text content of a page element:
template-json -selector:template#person
If you're iterating the object properties "blind," note that LiquidJS will turn properties into a two-element array, with the property name as the first element, and the property value as the second element.
Assuming data is an array of objects, this is how to manually generate a simple table.
<table>
<tr>
{% for field in data.first %}
<th>{{ field[0] }}</th>
{% endfor %}
</tr>
{% for row in data %}
<tr>
{% for field in row %}
<td>{{ field[1] }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Source Code
import { getLiquidEngine } from "../helpers.js";
async function templateJson(working, command, p) {
// Get all arguments upfront
const template = command.getArg("template");
const url = command.getArg("url");
const selector = command.getArg("selector");
if (template == null && url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch template from ${url}: ${response.status} ${response.statusText}`);
}
template = await response.text();
}
if (template == null && selector) {
const el = document.querySelector(selector);
if (!el) {
throw new Error(`Selector "${selector}" did not match any elements`);
}
template = el.innerHTML;
}
const engine = getLiquidEngine();
let data;
try {
data = JSON.parse(working.text);
} catch (e) {
// Swallow it, they might just use vars
}
try{
const renderedText = await engine.parseAndRender(template, {
data: data,
vars: Object.fromEntries(working.vars),
});
return renderedText;
} catch(e) {
throw new Error(`Error rendering template: ${e.message}`);
}
}
// Meta
templateJson.title = "Template JSON";
templateJson.description =
"Apply a Liquid template to JSON data to generate HTML. The entire working data is injected as an object in a variable called 'data'.";
templateJson.args = [
{
name: "template",
type: "string",
description: "Liquid template string",
},
{
name: "url",
type: "string",
description: "URL to fetch template from",
},
{
name: "selector",
type: "string",
description: "CSS selector to get template from DOM",
},
];
templateJson.parseValidators = [
{
test: (command) => {
return (
command.hasArg("template") ||
command.hasArg("url") ||
command.hasArg("selector")
);
},
message:
"You must provide a template, a URL to fetch a template from, or a templateSelector.",
},
];
export default templateJson;