How Eleventy Can Write Non-string Data in JavaScript with Nunjucks

A brief introduction a new Eleventy plugin: @sherby/eleventy-plugin-javascript 🎈

2 min read
How Eleventy Can Write Non-string Data in JavaScript with Nunjucks
Photo by THIS IS ZUN from Pexels

After I found how I could have valid JavaScript files with the front matter block, I rapidly come across a new challenge: how can I access non-string Eleventy data in JavaScript with Nunjucks? πŸ€”

It may seem easy at first, but the difficulty resides in that I still want to be able to lint my *.js.njk as JavaScript… Let me show you an example:

html: "Hello world!"
  - eleventy
  - javascript
  - html
import { LitElement, html } from 'lit-element';

class Post extends LitElement {
  render() {
    // Nunjunks variables are valid JavaScript inside a string
    const body = `{{ post.html }}`;
    // But outside, it will produce an error:
    //   "Uncaught SyntaxError: Unexpected token '{'"
    const tags = {{ post.tags }};
    return html`

window.customElements.define('br-post', Post);
Code example of a non-existent file named br-post.js.njk

Oops, I needed to find a workaround to that problem or my quick prototype to test if I could join Eleventy and Web Components will appear to be unsustainable… 😱

Fortunately, you may think that if I am writing this post, there is a good chance that I found a solution. And you are right. πŸ˜„ How? By using another time JavaScript comments. Let me show you how I came to that conclusion:

// Not valid JavaScript code :(
const anArray = {{ post.tags }};
const anObject = {{ }};

// could be converted into
const anArray = [ 
  // {{ post.tags }}
const anObject = { 
  // {{ }}

// and it would be valid, but our data would be inside JavaScript comments...
// Maybe a shortcode will help us transform our code
const anArray = [ 
  // {{ toJavaScriptArray post.tags }}
const anObject = { 
  // {{ toJavaScriptObject }}

// to the content of the array *on a subsequent line*
const anArray = [ 
  "eleventy", "javascript", "html"
const anObject = { 
  firstName: "Benjamin", lastName: "Rancourt"

// Oh oh, I think we may be into something! ;)

This solution may insert some blank comments, but if you minify your files before shipping them to production, they surely should be removed. πŸ§™

The shortcodes needed to do that are, in their simple forms, easy to implement:

const stringify = (object) => JSON.stringify(object);
const slice = (string) => string.slice(1, string.length - 1);
const decommentObject = (object) => `

eleventyConfig.addShortcode('toJavaScriptArray', decommentObject);
eleventyConfig.addShortcode('toJavaScriptObject', decommentObject);
Simple code that resolves our problem.

You could add and adapt these lines, but I recommend that you check on the @sherby/eleventy-plugin-javascript NPM package. I have included in it more robust functions to help you write JavaScript code with Eleventy. I also add some functionalities that I leave you to take a look at. πŸ˜‰

To use this plugin, you only need to install the dependency with npm

npm install @sherby/eleventy-plugin-javascript --save-dev
The Bash command to install the @sherby/eleventy-plugin-javascript module as a development dependency.

and to add the plugin into your Eleventy config file (.eleventy.js)

const eleventyPluginJavascript = require("@sherby/eleventy-plugin-javascript");
module.exports = (eleventyConfig) => {

Let me know if this plugin helps you! 🍬