DEV Community

loading...

Automation with Deno: a tiny text template processor in JavaScript

Andrew Nosenko
Dad, self-employed, problem solver at heart, async all the way. Formerly a principal software engineer at Nuance Communications. Occasionally I tweet, blog and answer my own StackOverflow questions.
Updated on ・3 min read

Basically, a three-liner:

const templateText = await Deno.readTextFile(Deno.args[0]);
const render = new Function("return `" + templateText + "`").bind(templateParams);
console.log(render());
Enter fullscreen mode Exit fullscreen mode

It uses interpolated JavaScript template strings (aka template literals) to process a generic text template file. For example:

# example of a YAML template
request:
  ip: ${ this.dateTime.client_ip }
  ip_time_zone: ${ this.dateTime.abbreviation }
  server_utc_time: ${ this.dateTime.utc_datetime }
  local_time: ${ new Date() }
Enter fullscreen mode Exit fullscreen mode

Here, this refers to the templateParams object we passed from the above Deno script. This text file is in fact just a multi-line template strings, with all the corresponding syntax rules you'd follow inside a JavaScript "backtick" string. Hey, it's even possible to use await inside `${...}` :)

What is this useful for?

I believe it can be useful for build automation, including certain CI/CD-related tasks.

Deno itself is a very self-cointained JavaScript/TypeScript runtime engine. It comes as a single executable file which can be used without any external dependencies. Yet it offers an extensive built-in API to deal with files, networking etc.

More so, any specific Deno version can be easily installed into a local folder without admin rights. E.g., to install Deno v1.10.3 on Windows with PowerShell:

# install Deno v1.10.3 into ./bin
$env:DENO_INSTALL = "$pwd"
$v="1.10.3"
iwr https://deno.land/x/install/install.ps1 -useb | iex
Enter fullscreen mode Exit fullscreen mode

Personally, I've never been comfortably fluent with Bash, PowerShell etc., so I find Deno very handy for quick, shell-like scripting with JavaScript. With Deno, I can quickly run a one-liner like this:

$ deno eval -p "await fetch('https://example.com').then(r => r.text()).then(t => t.match('example'))"
Enter fullscreen mode Exit fullscreen mode

Of course, Deno is much more capable than that, but that's outside the scope of this article.

An example of templating

This example is a bit contrived, but it illustrates the purpose. Here we make a simple fetch request to https://worldtimeapi.org/api/ip and save the results, using the above YAML template:

// deno run --allow-read --allow-net nascentTextGen.js sample.yaml.template 

const templateParams = {
  dateTime: await fetch("https://worldtimeapi.org/api/ip").then(r => r.json()),
  args: Deno.args
};

const templateText = await Deno.readTextFile(Deno.args[0]);
const render = new Function("return `" + templateText + "`").bind(templateParams);
console.log(render());
Enter fullscreen mode Exit fullscreen mode

Output:

# example of a YAML template
request:
  ip: a.b.c.d
  ip_time_zone: AEST
  server_utc_time: 2021-06-04T01:32:56.595373+00:00
  local_time: Fri Jun 04 2021 11:32:55 GMT+1000 (Australian Eastern Standard Time)
Enter fullscreen mode Exit fullscreen mode

Code

Clone or fork this simpe demo project. Then:

  • to install Deno (PowerShell):
pwsh -f _installDeno.ps1
Enter fullscreen mode Exit fullscreen mode
  • to run the sample:
pwsh -f _demo.ps1
Enter fullscreen mode Exit fullscreen mode

Some more advanced general-purpose templating tools

This little project was inspired by a search for a JavaScript-based general-purpose text templating tool.

Of course, this approach may only be useful for simple, "logic-less" templates. If you need branching and looping constructs like if, for, while or function, there are a lot more powerful and actively maintained alternatives out there:

Discussion (3)

Collapse
ihack2712 profile image
James Bradlee

This will not work on Deno deploy btw

Collapse
noseratio profile image
Andrew Nosenko Author

That makes sense for security reasons, but it works locally or inside a docker container.

Collapse
ihack2712 profile image
James Bradlee

It indeed does, I do however like the idea a lot, and wish it was possible in Deploy (for other reasons than running untrusted code)