# Core tags and attributes

Marko provides a number of tags

## Control flow

### `<if>`, `<else-if>`, `<else>`

The `<if>`, `<else-if>`, and `<else>` tags provide conditional control-flow for templates.

```marko
<if(arriving)>
    <div>Hey there</div>
</if>
<else-if(leaving)>
    <div>Bye now</div>
</else-if>
<else>
    <div>What's up?</div>
</else>
```

Conditionals may also be applied as attributes:

```marko
<div if(arriving)>Hey there</div>
<div else-if(leaving)>Bye now</div>
<div else>What's up?</div>
```

And support complex expressions:

```marko
<if(Math.random() > 0.5)>
    <div>50-50 chance of seeing this</div>
</if>
```

### `<for>`

The `<for>` tag allows iterating over an array of items:

```marko
<ul>
    <for(color in colors)>
        <li>${color}</li>
    </for>
</ul>
```

It may also be applied as an attribute:

```marko
<ul>
    <li for(color in colors)>${color}</li>
</ul>
```

With either of the above templates, and the following value for `colors`:

```js
var colors = ["red", "green", "blue"];
```

The output HTML would be the following:

```html
<ul>
    <li>red</li>
    <li>green</li>
    <li>blue</li>
</ul>
```

#### Loop Status Variable

The `for` directive also supports a loop status variable in case you need to know the current loop index. For example:

```marko
<ul>
    <li for(color in colors | status-var=loop)>
        ${color}
        ${loop.getIndex()+1}) of ${loop.getLength()}
        <if(loop.isFirst())> - FIRST</if>
        <if(loop.isLast())> - LAST</if>
    </li>
</ul>
```

##### Loop Status Methods

###### `getLength()`

Returns the length of the array

###### `getIndex()`

Returns the current loop index

###### `isFirst()`

Returns `true` if the current index is the first index, otherwise `false`

###### `isLast()`

Returns `true` if the current index is the last index, otherwise `false`

#### Loop Separator

Used for separating values in a loop by characters. The first element will not
be prefixed and the last element will not be suffixed with the `separator`:

```marko
<div>
    <!-- Output: red, green, blue -->
    <span for(color in colors | separator=", ") style="color: ${color}">
        ${color}
    </span>
</div>
```

#### Range Looping

A range can be provided in the following format; `<var-name> from <from> to <to>[ step <step>]`.

The `from`, `to` and `step` values must be numerical expressions. If not specified, step defaults to 1.

```marko
<ul>
    <li for(i from 0 to 10)>
        ${i}
    </li>
</ul>
```

```marko
<ul>
    <li for(i from 0 to 10 step 2)>
        ${i}
    </li>
</ul>
```

```marko
<ul>
    <li for(i from 0 to myArray.length-1)>
        ${myArray[i]}
    </li>
</ul>
```

#### Property Looping

```marko
<ul>
    <li for(name, value in settings)>
        <b>${name}</b>: ${value}
    </li>
</ul>
```

#### Native JavaScript for-loop

```marko
<for(var i=1; i<=3; i++)>
    ${i}
</for>
```

#### Custom Iterator

```marko
static function reverseIterator(arrayList, callback) {
    for(var i=arrayList.length-1; i>=0; i--){
        callback(arrayList[i]);
    }
}

<div for(item in ['a', 'b', 'c'] | iterator=reverseIterator)>
    ${item}
</div>
```

Output:

```html
<div>c</div>
<div>b</div>
<div>a</div>
```

### `<while>`

Any element can be repeated until a condition is met by using the `while` directive. The directive can be applied as an element or as an attribute.

_Applied as an attribute:_

```marko
$ var n = 0;

<ul>
    <li while(n < 4)>
        ${n++}
    </li>
</ul>
```

_Applied as an element:_

```marko
$ var n = 0;

<ul>
    <while(n < 4)>
        <li>${n++}</li>
    </while>
</ul>
```

### `body-only-if`

If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use the `body-only-if` attribute to handle this use case. For example, to only render a wrapping `<a>` tag if there is a valid URL then you could do the following:

```marko
<a href=input.linkUrl body-only-if(!input.linkUrl)>
    Some body content
</a>
```

Given a value of `"http://localhost/"` for the `input.linkUrl` variable: , the output would be the following:

```marko
<a href="http://localhost/">
    Some body content
</a>
```

Given a value of `undefined` for the `input.linkUrl` variable: , the output would be the following:

```marko
Some body content
```

## JavaScript

The following tags are always written using the [concise syntax](./concise.md), even when using HTML syntax for tags that generate HTML output.

### `import`

> **Static:** The code generated by `import` will run once when the template is loaded and be shared by all calls to render. It must be declared as a top level tag and does not have access to `data`, `state`, or other values passed in at render.

The `import` tag is used to access data and functions from external files. It follows the same syntax as the [JavaScript `import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).

```marko
import sum from './utils/sum';
<div>The sum of 2 + 3 is ${sum(2, 3)}</div>
```

<!-- ### `<export>`
> **Static:** The code generated by `export` will run once when the template is loaded and be shared by all calls to render. It must be declared as a top level tag and does not have access to `data`, `state`, or other values passed in at render.

The `export` tag is used to export values from the template.  It follows the same syntax as the [JavaScript `export` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export), but only named exports are supported (the default export is the template).

```marko
export var route = '/about';

<!doctype html>
<html>
    <body>
        <h1>About us</h1>
    </body>
</html>
``` -->

## `<${dynamic}>`

```marko
<${useDiv ? 'div' : 'span'}>
    Hello there!
</>
```

The `<${dynamic}>` tag is used to render a tag, component, or transcluded content that isn't determined until runtime.

### Dynamic components

The `<${dynamic}>` tag can be used to embed another template in the current template:

```marko
import componentA from "./path/to/component-a.marko";
import componentB from "./path/to/component-b.marko";

<${useA ? componentA : componentB} name="Frank"/>
```

You can also switch between a normal HTML tag and a Marko component:

```marko
import FancyButton from "./path/to/fancy-button.marko";

<${isFancy ? FancyButton : 'button'}>
    Button text
</>
```

### Layouts and transcluded content

You can pass transcluded content to a tag using nested attribute tags which are denoted by the `@` symbol:

_page.marko_

```marko
<layout>
    <@body>
        <h1>Hello Marko</h1>
    </@body>
</layout>
```

Then in your layout template you can render the transcluded content using the `<${dynamic}>` tag:

_layout.marko_

```marko
<!doctype html>
<html>
    <body>
        <!-- this comes from <@body> -->
        <${input.body}/>
    </body>
</html>
```

<!--
- You can use many nested attribute tags for multiple injection points
- You can have repeated nested attribute tags by using `marko-tag.json` (components only)
- You can add additional attributes to an nested attribute tag
- You can pass data to a nested attribute tag's body?
-->

### `<include-text>`

```marko
<include-text('./foo.txt')/>
```

Special HTML characters will be escaped. If you do not want escaping then use the `<include-html>` tag (see below).

### `<include-html>`

```marko
<include-html('./foo.html')/>
```

Special HTML characters will _not_ be escaped since the file is expected to be an HTML file.

### `<macro>`

Parameterized macros allow for reusable fragments within an HTML template.
A macro can be defined using the `<macro>` directive.

```marko
<macro greeting(name, count)>
    Hello ${name}! You have ${count} new messages.
</macro>
```

The above macro can then be invoked as part of any expression. The following
sample template shows how to use macro functions inside expressions:

```marko
<macro greeting(name, count)>
    Hello ${name}! You have ${count} new messages.
</macro>
<p>
    <greeting("John", 10)/>
</p>
<p>
    <!-- Or, using named attributes: -->
    <greeting name="Frank" count=20/>
</p>
```

## Async content

### `<await>`

The `<await>` tag is used to dynamically load in content from a data provider. The data provider can be a `Promise` or a `callback`. Once the provider returns it's results the children are rendered.

await-example.marko

```marko
$ var personPromise = new Promise((resolve, reject) => {
    setTimeout(function() {
        resolve({
            name: 'Frank'
        });
    }, 1000);
});

<await(person from personPromise)>
    <div>Hello ${person.name}!</div>
</await>
```

Advanced implementation:

- `<await>` tag signature
  - Basic usage: `<await(results from dataProvider)>...</await>`
  - Optional attributes
    - client-reorder `boolean`
    - arg `expression`
    - arg-\* `string`
    - method `string`
    - timeout `integer`
    - timeout-message `string`
    - error-message `string`
    - placeholder `string`
    - renderTimeout `function`
    - renderError `function`
    - renderPlaceholder `function`
    - name `string`
    - scope `expression`
    - show-after `string`
  - Optional child tags
    - `<await-placeholder>Loading...</await-placeholder>`
    - `<await-timeout>Request timed out</await-timeout>`
    - `<await-error>Request errored</await-error>`

## Comments

Standard HTML comments can be used to add comments to your template. The HTML comments will not show up in the rendered HTML.

Example comments:

```marko
<!-- This is a comment that will not be rendered -->
<h1>Hello</h1>
```

```js
// You can also use standard JavaScript-style comments
/*
 Block comments are also supported
 */
--Hello;
```

If you would like for your HTML comment to show up in the final output then you can use the custom `html-comment` tag.

### `<html-comment>`

_input.marko_

```marko
<html-comment>This is a comment that *will* be rendered</html-comment>
<h1>Hello</h1>
```

_output.html_

```html
<!--This is a comment that *will* be rendered-->
<h1>Hello</h1>
```

Alternatively, the `<marko-compiler-options>` tag may be used to configure comments for the entire template:

```marko
<marko-compiler-options preserve-comments/>
```

## Compiler options

### `marko-preserve-whitespace`

Whitespace can be preserved using the `preserve-whitespace` attribute:

```marko
<div marko-preserve-whitespace>
    All of this
    whitespace   will
    be preserved.
</div>
```

Alternatively, the `<marko-compiler-options>` tag may be used to configure whitespace for the entire template:

```marko
<marko-compiler-options preserve-whitespace/>
```

### `marko-body`

The `marko-body` attribute can be used to control how body content is parsed. The following values are supported:

- `html` - Body content will be parsed HTML (the default)
- `static-text` - Body content will be parsed as static text (HTML tags will be ignored). Placeholders will be ignored.
- `parsed-text` - Body content will be parsed as text (HTML tags will be ignored). Placeholders will not be ignored.

_input.marko_

```marko
<div marko-body="static-text">
    This is just one
    <span if(foo)>
            Hello ${THIS IS NOT VALID}!
    </span>
    big text block
</div>
```

_output.html_

```html
<div>
    This is just one
    &lt;span if(foo)&gt;
        Hello ${THIS IS NOT VALID}!
    &lt;/span&gt;
    big text block
</div>
```
