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>
’sof
attribute can loop over any iterable, just like JavaScript’sfor...of
. This includes strings,NodeList
s,Set
s… 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:
while
as 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 betweenTimeoutError
s 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-whitespace
Instead, 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-body
The 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.