Compile-time Tags
=================

Marko allows developers to control how a custom tag generates JavaScript code at compile-time. A custom compile-time tag developer can provide a "code generator" function for a custom tag.

# Custom tag code generator

Let's take a look at how to create a compile-time tag by providing our own code generator. The first step is to register the custom tag in a `marko-taglib.json` file. We will use the `code-generator` property to associate the custom tag with a function that will be used to generate the code for the element node at compile-time:

```json
{
    "<greeting>": {
        "code-generator": "./greeting-tag"
    }
}
```

A code generator module should export a function as shown below:

```javascript
module.exports =  function generateCode(elNode, generator) {
    // ...
}
```

The `elNode` argument will be an instance of [`HtmlElement`](../compiler/ast/HtmlElement.js). The `generator` argument will be an instance of [`CodeGenerator`](../compiler/CodeGenerator.js).

Continuing with the `<greeting>` example, let's assume we have the following template:

```xml
<greeting name="Frank"/>
```

Let's implement the greeting tag by generating code that will output `Hello Frank` using `console.log`:

```javascript
module.exports = function generateCode(elNode, generator) {
    var builder = generator.builder;

    return builder.functionCall('console.log', [
        builder.literal('Hello'),
        elNode.getAttributeValue('name')
    ]);
};
```

The above code results in the following compiled code:

```javascript
console.log("Hello", data.name);
```

In the example code above, the `generateCode(elNode, generator)` method returns a new [`FunctionCall`](../compiler/ast/FunctionCall.js) node using the provided [`Builder`](../compiler/Builder.js) instance. The builder provides methods for generating nodes associated with JavaScript primitives. This is the recommended way to produce JavaScript code since it ensures that code is generated correctly and with proper formatting.  However, for illustration purposes, the following also _works_ (just don't do it):

```javascript
module.exports = function generateCode(elNode, generator) {
    var nameValue = elNode.getAttributeValue('name');
    generator.write('console.log(');
    generator.write('"Hello"');
    generator.write(', ');
    generator.generateCode(nameValue);
    generator.write(')');
};
```

Writing to standard out using `console.log()` is probably _not_ what you want to do as a custom tag developer. You typically want to produce HTML output. Continuing with the same example, let's update our custom tag implementation to generate code that produces the following HTML output:

```html
<div class="greeting">Hello Frank</div>
```

To do that we will utilize the builder API to generate the appropriate tree of nodes:

```javascript
module.exports = function generateCode(elNode, generator) {
    var builder = generator.builder;

    return builder.htmlElement(
        'div',
        {
            'class': builder.literal('greeting')
        },
        [
            builder.text(builder.literal('Hello ')),
            builder.text(elNode.getAttributeValue('name'))
        ]);
};
```

For the following template:

```xml
<greeting name="Frank"/>
```

The code generated by the custom tag will be the following:

```javascript
out.w("<div class=\"greeting\">Hello Frank</div>");
```

For the following template, where the name is a non-literal JavaScript expression:

```xml
<greeting name=data.name/>
```

The code generated by the custom tag will be the following:

```javascript
out.w("<div class=\"greeting\">Hello " +
  marko_escapeXml(data.name) +
  "</div>");
```

# The Builder API

The Builder API plays a crucial role in generating code for a tag. The builder provides the building blocks for generating potentially complex JavaScript code.
