# Syntax Marko is HTML _re-imagined_ as a language for building dynamic and reactive user interfaces. Just about any valid HTML is valid Marko, but Marko extends the HTML language to allow building modern applications in a declarative way. > **ProTip:** Marko also supports a [beautiful concise syntax](./concise.md). If you'd prefer to see the documentation using this syntax, just click the `switch syntax` button in the corner of any Marko code sample. > **Note:** Text at the root of a template (outside any tags) must be prefixed with the [concise syntax's `--`](./concise.md#text) to denote it is text. The parser starts in concise mode and would otherwise try to parse what you meant to be text as a concise tag declaration. > > ```marko > -- Root level text > ``` ## Tags As you might expect, Marko supports all native HTML/SVG/whatever tags and attributes. In addition to these, it also comes with a set of useful [core tags](./core-tags.md). Beyond this, you can also build your own [custom tags](./custom-tags.md) and [install third-party tags](./custom-tags.md#using-tags-from-npm) from `npm`. All of these types of tags use the same syntax: ```marko ``` You don't need to import tags. Marko discovers them based on the folder structure—similar to how you don't specify a full path when referencing a module in `node_modules/`. Marko looks in [`components/`](./custom-tags.md#how-tags-are-discovered) by default and this directory can be configured in [`marko.json`](./marko-json.md). ## Dynamic text You can use placeholders (`${}`) to insert a value into the template: Placeholders accept any JavaScript expression and the result of the expression will be inserted into the HTML output: ```marko
Hello ${"world".toUpperCase()}
``` These values are automatically escaped so you don't accidentally insert malicious code. If you do need to pass unescaped HTML, you can use `$!{}`: ```marko
Hello $!{"World"}
``` > **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token: > > ```marko >
> Placeholder example: \${someValue} >
> ``` ## Attributes In marko attributes are parsed as JavaScript expressions (instead of just strings). ```marko
``` Attributes that are passed to a custom tag are received as it's [`input`](https://markojs.com/docs/class-components/#input). > **Note:** Although in most cases you won't see a difference, strings are parsed as JavaScript strings, not HTML strings. Where this comes up most often is using the `pattern` attribute with the `` tag: you need to "double escape" your regex escape sequences much like you were passing a string to the [`RegExp` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) (or you can use a literal `/regex/`). > > _Marko Source:_ > > ```marko > > > ``` > > _HTML Output:_ > > ```html > > ``` ### Complex expressions Any JavaScript expression is a valid attribute value, provided it meets the following criteria: _It does not contain any spaces_ _It does not contain any right angle brackets (`>`)_ ```marko ``` ```marko custom-tag sum=1+2 difference=3-4 ``` _Spaces and `>` are contained within matching `()`, `[]`, `{}`, strings and regexps_ ```marko 2)/> ``` ```marko custom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2) ``` ### Boolean attributes HTML defines the following rules for [boolean attributes](https://www.w3.org/TR/2008/WD-html5-20080610/semantics.html#boolean): > The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value. In Marko when an attribute value evaluates to `false`, `null`, or `undefined`, the attribute is not included in the output. If an attribute value is `true`, only the attribute name is included in the output. _Marko Source:_ ```marko ``` Renders the following HTML: _HTML Output:_ ```html ``` Similarly, when only an attribute name is defined, it is equivalent to specifying the attribute with a value of `true`: ```marko ``` > **ProTip:** > You can take advantage of the way Marko handles boolean attributes to conditionally render attributes: > > _Marko Source:_ > > ```marko >
Hello
> ``` > > With a value of `true` for `active`, the output would be the following: > > _HTML Output:_ > > ```html >
Hello
> ``` > > With a value of `false` for `active`, the output would be the following: > > _HTML Output:_ > > ```html >
Hello
> ``` ### Dynamic attributes The spread syntax (`...`) can be used to merge in an object as attributes to a tag: _Marko Source:_ ```marko eBay ``` With `attrs` as the following value: ```js { class: "active", href: "https://ebay.com/" } ``` would output the following HTML: _HTML Output:_ ```html eBay ``` > **ProTip:** > With spread attributes order matters. > You can take advantage of this to implement both default attributes, and enforced attributes. > > ```marko > > ``` > **ProTip:** > You can provide `undefined` to a spread attribute which will output nothing. ### Style attribute You can pass a string as the value of `style` just as you would in HTML, in addition Marko supports passing an object or array as the value of the `style` attribute: _Marko Source:_ ```marko
``` In all cases, the output will be the same: _HTML Output:_ ```html
``` ### Class attribute The `class` attribute also supports receiving an object or array (in addition to a string) as shown below: _Marko Source:_ ```marko
``` In all cases, the output will be the same: _HTML Output:_ ```html
``` ### Shorthand attributes Marko provides a shorthand for declaring classes and ids on an element, including interpolation. Given `size` is the string `small`: _Marko Source:_ ```marko ``` Renders the following HTML: _HTML Output:_ ```html
``` ## Parameters When a tag renders its body content, it may provide data which can be received by defining parameters after the tagname. Parameters are available to the tag's body content. This is a powerful feature that allows components to provide functionality and data while giving you full control over what gets rendered. In the following example, `` provides a parameter which we have named `position`: ```marko The mouse is at ${position.x}, ${position.y}! ``` > `` would [render its body](./body-content.md) and provide the position similar to this: `<${input.renderBody} x=0 y=0/>`. > **ProTip:** Tag `|parameters|` are treated as regular JavaScript function parameters. This means you can destructure, set default values, etc. > > ```marko > > The mouse is at ${x}, ${y}! > > ``` > **Note:** Parameters are not available to attributes, only to the tag body. > > ```marko > > ReferenceError when setting the "something" attribute > > ``` Parameters are used by some of Marko's [core tags](./core-tags.md) like the [``](./core-tags.md#for) and [``](./core-tags.md#await) tags. ## Arguments Some tags and attributes accept javascript style `arguments`. Arguments are denoted by parenthesis following the tag or attribute name. Arguments provide a way to pass unnamed data to a tag. ```marko Marko is awesome

Conditional display heading, but always show content!

``` Arguments are used by some of Marko's [core tags](./core-tags.md) like the [``](./core-tags.md#if-else-if-else) tag and [`body-only-if`](./core-tags.md#body-only-if) attribute displayed above. Previously you could also use them in your own [custom tags](./custom-tags.md) however it is now recommended to use [dynamic attributes](#dynamic-attributes). ## Dynamic tagname The `<${dynamic}>` syntax is used to render a tag or component that isn't determined until runtime. It can also be used within a [custom tag](./custom-tags.md) to render body content that was passed to that tag. _Marko Source:_ ```marko <${href ? 'a' : 'button'} href=href> Click me! ``` With `href` as `https://ebay.com` would output the following HTML: _HTML Output:_ ```html Click me! ``` And with `href` as `undefined` would output the following HTML: _HTML Output:_ ```html ``` As a shorthand if there is a variable in scope and [no other matching tag is discovered](#how-tags-are-discovered) the wrapping `${}` is unnecessary. For example the following are equivalent: ```marko $ const MyTag = href ? 'a' : 'button'; <${MyTag}/> ``` > **ProTip:** > If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use a null dynamic tag. For example, to only render a wrapping `` tag if there is a valid URL then you could do the following: > > _Marko Source:_ > > ```marko > <${input.linkUrl ? "a" : null} href=input.linkUrl > > Some body content > > ``` > > Given a value of `"http://localhost/"` for the `input.linkUrl` variable: , the output would be the following: > > _HTML Output:_ > > ```html > Some body content > ``` > > Given a value of `undefined` for the `input.linkUrl` variable: , the output would be the following: > > _HTML Output:_ > > ```html > Some body content > ``` ### Dynamic components Instead of just strings, the dynamic tagname can also be a component: ```marko import componentA from ""; import componentB from ""; <${useA ? componentA : componentB}/> ``` > **ProTip:** > You can also switch between a normal HTML tag and a component: > > ```marko > import FancyButton from ""; > > <${isFancy ? FancyButton : 'button'}> > Button text > > ``` > **Note:** You **cannot** reference a Marko custom tag or macro using a name string: > > _Marko Source:_ > > ```marko > <${isFancy ? 'fancy-button' : 'button'}> > Button text > > ``` > > With `isFancy` as `true` would output the following HTML: > > _HTML Output:_ > > ```html > Button text > ``` ### Dynamic body content When a custom tag receives [body content](./body-content.md), it is passed as a `renderBody` property. To render this content you can pass the `renderBody` as the dynamic tagname. ```marko
<${input.renderBody}/>
``` ## Attribute Tag As the name implies, `<@attribute-tags>` are special attributes that take the form of tags. They allow you to pass named body sections to a [custom tag](./custom-tags.md). The core `` tag allows you to pass multiple body sections that it will conditionally render based on the state of the promise. ```marko <@then|result|> The promise resolved: ${result} <@catch|error|> The promise rejected: ${error.message} ``` These body sections are also commonly used to create layouts: ```marko <@heading>

Hello

<@body>

Lorem ipsum....

``` These tags are passed to the custom tag as objects with a `renderBody`, it can then [render its body content](./body-content.md). > **Note:** > Attribute tags can have their own parameters, but like attributes, they cannot access the parameters of their parent tag: > > ```marko > > ${item.name} > <@separator>${item} (oops, ReferenceError) > > ``` ## Inline JavaScript To execute JavaScript in your template you can insert a Javascript statement using the `$ ` syntax. A line that starts with a `$` followed by a space will execute the code that follows. ```marko $ const name = "World";
Hello, ${name} $ console.log("The value rendered was", name);
``` A statement may continue onto subsequent lines if new lines are bounded by `{}`, `[]`, `()`, ` `` `, or `/**/`: ```marko $ const person = { name: "Frank", age: 32 }; ``` Multiple statements or an unbounded statement may be used by wrapping the statement(s) in a block: ```marko $ { const bgColor = getRandomColor(); const textColor = isLight(bgColor) ? "black" : "white"; } ``` > **ProTip:** Any JavaScript statement can be used here, even `debugger`: > > ```marko >
> ${textColor} > $ debugger; // Quickly debug `textColor` >
> ``` > **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token: > > ```marko >

You can run JS in a Marko template like this:

> > \$ var num = 123; > > ``` > **ProTip:** If you find yourself writing a lot of inline JS, consider moving it out to an external file and then [`import`](#importing-external-files) it. ### Static JavaScript Inline JavaScript will run each time your template is rendered, but the JavaScript code that follows `static` will only run once when the template is loaded. It must be declared at the top level and does not have access to values passed in at render time. ```marko static var count = 0; static var formatter = new Formatter(); static function sum(a, b) { return a + b; };
${formatter.format(sum(2, 3))}
``` Like inline Javascript, multiple statements or an unbounded statement may be used by wrapping the statement(s) in a block: ```marko static { var base = 2; function sum(a, b) { return base + a + b; }; } ``` ### Importing external files The `import` statement 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';
The sum of 2 + 3 is ${sum(2, 3)}
``` As a shorthand you can also import components by providing it's html tag name wrapped in angle brackets, eg: ```marko import MyComponent from "" ``` This is especially useful with the [dynamic tag name syntax](./syntax.md#dynamic-tagname) and uses the same [component discovery](./custom-tags.md#how-tags-are-discovered) as if the tag was used in the template. ## Comments Standard HTML comments can be used and will be stripped out of the rendered output. At the top level of the template JavaScript comments (`// comment` and `/** comment */`) can also be used. ```marko

Hello

``` If you would like for your HTML comment to show up in the final output then you can use the [`html-comment` core tag](./core-tags.md#html-comment).