Handlebars is an excellent templating engine. The basic usage is as follows:

const str = `My name is {{name}}, I'm {{age}} years old`
const data = {name: 'keliq'.age: 10}
console.log(require('handlebars').compile(str)(data))
// Get: My name is Keliq, I'm 10 years old
Copy the code

How does it work on the inside? There are only three steps:

Step 1: Parse the template

The purpose of parsing the template is to put the following strings:

My name is {{name}}, I'm {{age}} years old
Copy the code

Becomes the following array:

[ 'My name is '.'{{name}}'.", I'm ".'{{age}}'.' years old' ]
Copy the code

The analytic function is as follows:

var parse = (tpl) = > {
  let result, firstPos
  const arr = []
  while (result = / {{(. *?) }}/g.exec(tpl)) {
    firstPos = result.index
    if(firstPos ! = =0) {
      arr.push(tpl.substring(0, firstPos))
      tpl = tpl.slice(firstPos)
    }
    arr.push(result[0])
    tpl = tpl.slice(result[0].length)
  }
  if (tpl) arr.push(tpl)
  return arr
}
Copy the code

Step 2: Construct the expression

Construct an expression by parsing the result of the first step:

[ 'My name is '.'{{name}}'.", I'm ".'{{age}}'.' years old' ]
Copy the code

Convert to the following JS expression:

""+"My name is "+data.name+", I'm "+data.age+" years old"
Copy the code

The implementation of this step is relatively simple, is the string, the code is as follows:

const compileToString = (tokens) = > {
  let fnStr = ` "" `
  tokens.map(t= > {
    if (t.startsWith({{" ") && t.endsWith("}}")) {
      fnStr += `+data.${t.split(/ / {{|}}).filter(Boolean) [0].trim()}`
    } else {
      fnStr += ` +"${t}"`}})return fnStr
}
Copy the code

Step 3: Create the render function

We already got the JS expression in step 2, but it’s essentially just a string:

""+"My name is "+data.name+", I'm "+data.age+" years old"
Copy the code

So how does that work? You can do this by creating functions dynamically with new Function:

const compile = (tpl) = > {
  return new Function("data"."return " + compileToString(parse(tpl)))
}
Copy the code

This implements the compile function for Handlebars, so let’s run it:

console.log(compile(str)(data))
// My name is keliq, I'm 10 years old
Copy the code