
Much like HTML has its own native tags, Marko includes core tags and global attributes for declaratively building modern applications.
<if>, <else-if>, <else>Like the equivalent JavaScript statements, these tags render conditional content:
<ifarriving>Hey there</if><else-ifleaving>Bye now</else-if><else>What’s up?</else>
ifarriving -- Hey thereelse-ifleaving -- Bye nowelse -- What’s up?
They support any JavaScript expression in their tag arguments:
<ifMath.random > 0.5><p>50% chance to see this</p></if>
ifMath.random > 0.5p -- 50% chance to see this
Note: The alternate conditional attribute syntax is deprecated:
<p ifarriving)>Hey there</p><p else-ifleaving>Bye now</p><p else>What’s up?</p>p ifarriving) -- Hey therep else-ifleaving) -- Bye nowp else -- What’s up?
<for>The <for> tag iterates over arrays/array-likes, object properties, and ranges of numbers.
Note: You may see
for()as a tag or attribute. This kinda-like-JS-but-not-really syntax is deprecated:<li forcolor in colors)></li>li forcolor in colors) --
Like the JavaScript for...of loop statement, giving <for>’s of attribute a value will loop over that value as an array or iterable.
The current item, index, and the iterating list are provided as tag parameters:
<ol><forcolor, index, colorList of=colors><li value=index></li></for></ol>
olforcolor, index, colorList of=colorsli value=index --
The output HTML would be:
redgreenblue
Pro Tip:
<for>’sofattribute can loop over any iterable, just like JavaScript’sfor...of. This includes strings,NodeLists,Sets… any object with zero-indexed numeric properties and a.length, basically.
Like JavaScript’s for...in loop statement, giving <for> an object as its in attribute will loop over that object’s properties.
The current property name and property value are provided as tag parameters:
<dl><forname, enabled in=settings><dt>:</dt><dd></dd></for></dl>
dlforname, enabled in=settingsdt -- :dd --
The output HTML would be:
Dark Mode:offFullscreen:on
The final <for> variant loops between two numbers, by providing from and to attributes. The current number in the range will be provided as a tag parameter:
<ol type="I"><fori from=0 to=10><li value=i></li></for></ol>
ol type="I"fori from=0 to=10li value=i --
You can also pass an optional step attribute, which defaults to 1 otherwise. step lets you increment by a specific amount:
<ol type="I"><fori from=0 to=10 step=2><li value=i></li></for></ol>
ol type="I"fori from=0 to=10 step=2li value=i --
…becomes:
<ol type="I"><li value="0">0</li><li value="2">2</li><li value="4">4</li><li value="6">6</li><li value="8">8</li><li value="10">10</li></ol>
ol type="I"li value="0" -- 0li value="2" -- 2li value="4" -- 4li value="6" -- 6li value="8" -- 8li value="10" -- 10
ProTip: This syntax is for generating numbers from nothing. Don’t use it to iterate over an object, like so:
<!-- Inefficient code, do not copy --><ul><fori from=0 to=myArray.length - 1><li></li></for></ul>// Inefficient code, do not copyulfori from=0 to=myArray.length - 1li --Use
<for of>instead.
<while>Warning: Using
<while>is not recommended. Instead, replicate it with an iterable and<for>.In the future, Marko may restrict value mutation during rendering, for runtime optimizations.
You can repeat a chunk of markup until a condition is met with the while tag:
<whilen < 4><p></p></while>
whilen < 4p --
…becomes:
0123
Note:
whileas an attribute is deprecated:<p whilen < 4)></p>p whilen < 4) --
<macro>Macros create reusable markup fragments for later use in the same template they were defined in.
The <macro> tag defines a macro as a tag via the name attribute. For example, the following macro is registered as the <greeting> tag:
<macro name="greeting"><p>Welcome!</p></macro><greeting/><greeting/>
macro name="greeting"p -- Welcome!greetinggreeting
…the output HTML would be:
Welcome!Welcome!
Macros become more useful with tag parameters, allowing complex templates. In this next example, <greeting> can now receive firstName and count parameters from its parent:
<macro{ firstName, count } name="greeting"><p>Hello !<output>You have new messages.</output></p></macro><greeting firstName="Frank" count=20/>
macro{ firstName, count } name="greeting"pgreeting firstName="Frank" count=20
…the output HTML would be:
Hello Frank!You have 20 new messages.
Macros receive input like components do, including a renderBody for provided body content:
<macro{ renderBody } name="special-heading"><h1></>!</h1></macro><special-heading>Hello</special-heading>
macro{ renderBody } name="special-heading"h1-- </>!special-heading -- Hello
…the output HTML would be:
Hello!
ProTip: You can use a macro inside itself for recursive layouts, like displaying directory contents.
<await>The <await> tag renders markup asynchronously using a Promise.
<@then> attribute tag displays when the Promise resolves, optionally receiving the resolved value as a tag parameter.<@catch> attribute tag displays when the Promise rejects, optionally receiving the rejected value as a tag parameter.<@placeholder> attribute tag displays while the Promise is pending.<awaitpersonPromise><@placeholder><!-- Displays while promise is pending --><label>Loading…<progress></progress></label></@placeholder><@thenperson><!-- Displays if promise resolves --><p>Hello !</p></@then><@catcherr><!-- Displays if promise rejects -->error:</@catch></await>
awaitpersonPromise@placeholder// Displays while promise is pendinglabel-- Loading…progress@thenperson// Displays if promise resolvesp -- Hello !@catcherr<!-- Displays if promise rejects --> error:
Optional attributes for <await>:
| Attribute | Type | Description |
|---|---|---|
timeout | integer | An optional timeout. If reached, rejects the promise with a TimeoutError. |
name | string | Improves debugging and ensures ordering with the show-after attribute. |
show-after | string | Another <await> tag’s name. With client-reorder, ensures that the current <await> block will always show after the named <await>. |
client-reorder | boolean | If true, anything after this <await> will be server-rendered before the Promise completes, then the fulfilled Promise’s result will be updated with client-side JavaScript. |
Pro Tip: When using
timeout, you can distinguish betweenTimeoutErrors and promise rejections by checking the error’sname:<awaitslowPromise timeout=5000><@then>Done</@then><@catcherr><iferr.name === "TimeoutError">Took too long to fetch the data!</if><else>Promise failed with .</else></@catch></await>awaitslowPromise timeout=5000@then -- Done@catcherriferr.name === "TimeoutError" -- Took too long to fetch the data!else -- Promise failed with .
<include-text><include-text> inlines text files into a template, escaping HTML syntax characters (<, ", etc.).
<include-text'./foo.txt'/>
include-text"./foo.txt"
If you do not want escaping, use <include-html> instead.
<include-html>Like <include-text>, <include-html> inlines the contents of a file. However, this tag does not escape special HTML characters.
<include-html'./foo.html'/>
include-html"./foo.html"
<html-comment>Marko removes HTML comment tags from its output. But if you need comments in the output, that’s what <html-comment> is for:
<html-comment>[if IE]><script src="html-shiv.js"></script><![endif]</html-comment>
html-comment -- [if IE]><script src="html-shiv.js"></script><![endif]
…becomes:
<!--[if IE]><script src="html-shiv.js"></script><![endif]-->
Note: You might see the deprecated
<marko-compiler-options>tag used to configure comments for the template:<marko-compiler-options preserve-comments/>marko-compiler-options preserve-comments
The following tags and attributes are deprecated, but you might see them in older code.
marko-preserve-whitespaceInstead, preserve whitespace with the preserve-whitespace attribute:
style {}<p>You’ll get an error with that line of Python,as it has one too many spaces as indentation:<code.lang-python marko-preserve-whitespace> <mark> </mark>frobulate()</code></p>
style {}p<code.lang-python marko-preserve-whitespace> <mark> </mark>frobulate()</code>
marko-bodyThe marko-body attribute controls how a tag’s body content is parsed, with the following possible values:
html (default) — Body content is parsed as HTML.static-text — Body content is parsed as static text, ignoring HTML tags and dynamic text ${placeholders}.parsed-text — Body content is parsed as text, ignoring HTML tags. Does not ignore ${placeholders}.<p marko-body="static-text">This is just one<b malformed-attribute=">Hello ${THIS IS NOT VALID}!</b>big text block</p>
p marko-body="static-text"
…becomes:
EDITThis is just one <b malformed-attribute="> Hello ${THIS IS NOT VALID}!</b> big text block
Helpful? You can thank these awesome people! You can also edit this doc if you see any issues or want to improve it.