skull

Robert Tamayo

R
B
blog
skull

Enhancing the Simple JavaScript Template Renderer

Previously, I wrote about making a simple JavaScript template renderer. It was basically a simple function that would take data in JSON format and use it to render a template.
Recently, I needed to enhance it a little. I originally built it so that I wouldn't have to pull in a 3rd party library that included a bunch of features I didn't need, and since the client in particular was concerned with page load speed, I decided to build a slim version. This recent enhancement adds a layer of complexity, unfortunately, but it's fun nonetheless.

I added simple functions that will let you modify the templates to make the data appear as uppercase, lowercase, or with a default value.

Here is a quick example:



The output is:

This is accomplished like so:

1. Decide a syntax to use for the templates


Mine looks like this:

let template = `
    Hello {{firstname#uppercase#}} 
    {{lastname#lowercase#}}. 
    Your RPG character class is: {{blank#ifempty:Wizard#}}.
`;

The #'s separate the function from the key, and the text to the right of the "ifempty:" specifies the default value to display if the value of the key in the data is empty.

2. Add the new function-handling code


const _functionRegex = /{{[\w\s:\.]+#.*#}}/g;
const functionNames = [
    'ifempty',
    'uppercase',
    'lowercase'
];
const functionDefinitions = {
    ifempty: function(value, args) {
        if (value == '') {
            value = args.replace('ifempty:', '');
        }
        return value;
    },
    uppercase: value => value.toUpperCase();
    },
    lowercase: function(value){
        return value.toLowerCase();
    }
}

3. Process value-modifying matches second


I didn't want to affect performance on templates that don't need special modifications, so I added the following code as a second pass-through to the original function.

// function pass
matches = html.match(_functionRegex);
if (matches && matches.length) {
    length = matches.length;
    for (i = 0; i < length; i++) {
        match = matches[i];
        name = match.replace(_bracketsRegex, '');
        let split = name.split('#');
        let key = split[0];
        let args = split[1];
        let value = '';
        let dataValue = data[key] || '';
        functionNames.forEach((f)=>{
            if (args.indexOf(f) !== -1) {
                value = functionDefinitions[f](dataValue, args);
            }
        });
        html = html.replace(match, value);
    }
}
return html;

That's all there is to it.

Because I built this blog platform from scratch, it doesn't have many features. One of the features it didn't have before today was the ability to add code blocks as html to the page. This is the first post I wrote to test out that feature. The next post I'm writing required this feature to be built in the first place. It's going to cover a topic I really care about, and one that I'm also excited to learn more about: WebGL and Procedural Graphics.
Comments:
Leave a Comment
Submit