Skip to content
Kyle Robinson Young edited this page Mar 20, 2016 · 3 revisions

bel is a module that takes the output from a tagged template string and creates a DOM element tree.

bel relies on a few concepts and dependencies:

  • tagged template literals
  • hyperx

Tagged template literals

Regular template literals lets you take code like this:

var multiline = 'hello\n' +
'this\n' +
'is\n' +
'multiline'

And write the same thing like this instead:

var multiline = `hello
this
is
multiline`

Tagged template literals is where you put a function name in front of the template tags, similar to calling a function with () but using the backticks ```` instead of parens.

function doesNothing () {}

doesNothing`im a string`

The above example causes the doesNothing function to get invoked (AKA called), similar to if you did doesNothing('im a string').

The difference is that tagged template strings return a specific output value.

function logArguments (a, b, c, d) {
  console.log(a, b, c, d)
}

logArguments`im a string`

Running the above produces ["im a string", raw: "im a string"] undefined undefined undefined.

If you were to just run console.log(im a string) it would produce "im a string".

However, tagged template strings return the above tagged template array output format.

The first item in the array is an array of all of the strings in your template string. In our case there is only one:

["im a string", raw: "im a string"]

The raw is a property that also contains an array, but where the values are the 'raw' values as there were entered.

If you had this template for example:

logArguments`\u9999`

It would produce this as the first argument to logArguments: ["香", raw: ["\u9999"]]

In template literals, tagged or not, you can interpolate values by embedding javascript expressions inside of ${}

var name = 'bob'
console.log(`hello ${name}!`)

The above produces "hello bob!". However, when called like this:

function logArguments (a, b, c, d) {
  console.log(a, b, c, d)
}

var name = 'bob'
logArguments`hello ${name}!`

It produces the tagged template array ["hello ", "!", raw: ["hello ", "!"]] "bob" undefined undefined

As you can see the first argument is an array of all of the strings, and the rest of the arguments are all of the interpolated values one at a time.

Using this array you can implement your own custom way to render the strings and values. For example to simply print a string you print the strings and values in 'zipped' order):

function printString(strings, valueA, valueB, valueC) {
  console.log(strings[0] + valueA + strings[1] + valueB + strings[2] + valueC)
}

You could also imagine writing the above function in a more general way using loops etc. Or do something entirely different:

hyperx

bel uses a module called hyperx to turn tagged template arrays into DOM builder data.

For example:

var hyperx = require('hyperx')

var convertTaggedTemplateOutputToDomBuilder = hyperx(function (tagName, attrs, children) {
  console.log(tagName, attrs, children)
})

convertTaggedTemplateOutputToDomBuilder`<h1>hello world</h1>`

Running this produces h1 {} [ 'hello world' ], which aren't yet DOM elements but have all the data you need to build your own DOM elements however you like. These three arguments, tagName, attrs, children are a sort of pseudo-standard used by various DOM building libraries such as virtual-dom, hyperscript and react, and now bel.

As you can see in the source, bel creates new elements using the DOM builder arguments from hyperx.

You can also use DOM elements not created using bel:

var bel = require('bel')
var nonBelElement = document.createElement('h3')
nonBelElement.textContent = 'Hello'

var app = bel`<div class="app">${nonBelElement} World</div>`

Running the above sets app to an element with this HTML:

<div class="app"><h3>Hello</h3> World</div>