Skip to content

Commit 633a40e

Browse files
committed
Add Template operation for basic JSON rendering
1 parent 7c8be12 commit 633a40e

File tree

6 files changed

+127
-3
lines changed

6 files changed

+127
-3
lines changed

package-lock.json

+28-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
"file-saver": "^2.0.5",
133133
"flat": "^6.0.1",
134134
"geodesy": "1.1.3",
135+
"handlebars": "^4.7.8",
135136
"highlight.js": "^11.9.0",
136137
"ieee754": "^1.2.1",
137138
"jimp": "^0.22.12",

src/core/config/Categories.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@
373373
"Extract EXIF",
374374
"Extract ID3",
375375
"Extract Files",
376-
"RAKE"
376+
"RAKE",
377+
"Template"
377378
]
378379
},
379380
{

src/core/operations/Template.mjs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @author kendallgoto [k@kgo.to]
3+
* @copyright Crown Copyright 2025
4+
* @license Apache-2.0
5+
*/
6+
7+
import Operation from "../Operation.mjs";
8+
import OperationError from "../errors/OperationError.mjs";
9+
import Handlebars from "handlebars";
10+
11+
/**
12+
* Template operation
13+
*/
14+
class Template extends Operation {
15+
16+
/**
17+
* Template constructor
18+
*/
19+
constructor() {
20+
super();
21+
22+
this.name = "Template";
23+
this.module = "Handlebars";
24+
this.description = "Render a template with Handlebars/Mustache substituting variables using JSON input.";
25+
this.infoURL = "https://handlebarsjs.com/";
26+
this.inputType = "JSON";
27+
this.outputType = "html";
28+
this.args = [
29+
{
30+
name: "Template definition (.handlebars)",
31+
type: "text",
32+
value: ""
33+
}
34+
];
35+
}
36+
37+
/**
38+
* @param {JSON} input
39+
* @param {Object[]} args
40+
* @returns {html}
41+
*/
42+
run(input, args) {
43+
const [templateStr] = args;
44+
try {
45+
const template = Handlebars.compile(templateStr);
46+
return template(input);
47+
} catch (e) {
48+
throw new OperationError(e);
49+
}
50+
}
51+
}
52+
53+
export default Template;

tests/operations/index.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ import "./tests/Subsection.mjs";
157157
import "./tests/SwapCase.mjs";
158158
import "./tests/SymmetricDifference.mjs";
159159
import "./tests/TakeNthBytes.mjs";
160+
import "./tests/Template.mjs";
160161
import "./tests/TextEncodingBruteForce.mjs";
161162
import "./tests/ToFromInsensitiveRegex.mjs";
162163
import "./tests/TranslateDateTimeFormat.mjs";

tests/operations/tests/Template.mjs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* @author kendallgoto [k@kgo.to]
3+
* @copyright Crown Copyright 2025
4+
* @license Apache-2.0
5+
*/
6+
7+
import TestRegister from "../../lib/TestRegister.mjs";
8+
TestRegister.addTests([
9+
{
10+
"name": "Template: Simple Print",
11+
"input": "{}",
12+
"expectedOutput": "Hello, world!",
13+
"recipeConfig": [
14+
{
15+
"op": "Template",
16+
"args": ["Hello, world!"]
17+
}
18+
]
19+
},
20+
{
21+
"name": "Template: Print Basic Variables",
22+
"input": "{\"one\": 1, \"two\": 2}",
23+
"expectedOutput": "1 2",
24+
"recipeConfig": [
25+
{
26+
"op": "Template",
27+
"args": ["{{ one }} {{ two }}"]
28+
}
29+
]
30+
},
31+
{
32+
"name": "Template: Partials",
33+
"input": "{\"users\":[{\"name\":\"Someone\",\"age\":25},{\"name\":\"Someone Else\",\"age\":32}]}",
34+
"expectedOutput": "Name: Someone\nAge: 25\n\nName: Someone Else\nAge: 32\n\n",
35+
"recipeConfig": [
36+
{
37+
"op": "Template",
38+
"args": ["{{#*inline \"user\"}}\nName: {{ name }}\nAge: {{ age }}\n{{/inline}}\n{{#each users}}\n{{> user}}\n\n{{/each}}"]
39+
}
40+
]
41+
}
42+
]);

0 commit comments

Comments
 (0)