Mustache.jl#
Documentation for Mustache.jl.
Examples#
Following the main documentation for Mustache.js we have a "typical Mustache template" defined by (along with a bit of an anti-tax sentiment):
using Mustache
tpl = mt"""
Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/in_ca}}
"""
MustacheTokens
Mustache.TextToken("text", "Hello ")
Mustache.TagToken("name", "name", "{{", "}}", "")
Mustache.TextToken("text", "\nYou have just won ")
Mustache.TagToken("name", "value", "{{", "}}", "")
Mustache.TextToken("text", " dollars!\n")
SectionToken("#", "in_ca", "{{", "}}")
Mustache.TextToken("text", "Well, ")
Mustache.TagToken("name", "taxed_value", "{{", "}}", "")
Mustache.TextToken("text", " dollars, after taxes.\n")
The values with braces (mustaches on their side) are looked up in a view, such as a dictionary or module. For example,
d = Dict(
"name" => "Chris",
"value" => 10000,
"taxed_value" => 10000 - (10000 * 0.4),
"in_ca" => true)
Mustache.render(tpl, d) |> print
Hello Chris
You have just won 10000 dollars!
Well, 6000.0 dollars, after taxes.
The render function pieces things together. Like print, the first argument is for an optional IO instance. In the above example, where one is not provided, a string is returned. (The print call is for formatting purposes.)
The flow is
a template is parsed into tokens by
Mustache.parse. This can be called directly, indirectly through the non-standard string literalmt, the non-standard string literaljmt(which allows for string interpolation), or when loading a file withMustache.load. The templates use tags comprised of matching mustaches ({}), either two or three, to indicate a value to be substituted for. These particular symbols indicating tags may be adjusted whenparseis called.The tokens and a view are
rendered into a string. Therenderfunction takes tokens as its second argument. If this argument is a string,parseis called internally. Therenderfunction than reassambles the template, substituting values, as appropriate, from the "view" passed to it and writes the output to the specifiedioargument.
There are only 4 exports: mt and jmt (string literals to specify a template), render, and render_from_file.
The pipeline#
A template is specified and rendered with values coming from a view. This section gives some more detail.
Rendering#
The render function combines tokens and a view to fill in the template. The basic call is render([io::IO], tokens, view), however there are variants:
render(tokens; view...)render(tokens; kwargs...)
Or (wherestring is parsed into tokens before rendering):
render(string, view)render(string; kwargs...)
MustacheTokens objects are functors; keyword arguments can also be passed to a Tokens object directly which resolves to calling render.
tokens([io::IO], view)tokens([io::IO]; kwargs...)
For example:
goes_together = mt"{{{:x}}} and {{{:y}}}."
goes_together(; x="Fish", y="chips")
"Fish and chips."
Views#
Views are used to hold values for the templates variables. There are many possible objects that can be used for views:
a dictionary
a named tuple
keyword arguments to
rendera composite type
a module
data frame
The tags are looked up in the context of a view, so the view is used to provide values to substitute into the template. The lookup allows for different types of view. The above example used a dictionary. A Module may also be used, such as Main:
name, value, taxed_value, in_ca = "Christine", 10000, 10000 - (10000 * 0.4), false
Mustache.render(tpl, Main) |> print
Hello
You have just won dollars!
Which yields:
Hello Christine
You have just won 10000 dollars!
Similarly, a named tuple may be used as a view.
tpl(; name="Bill", value=1, taxed_value =0.5, in_ca = true) |> print
Hello Bill
You have just won 1 dollars!
Well, 0.5 dollars, after taxes.
As well, one can use composite types. This could make writing show methods easier (though string interpolation is as easy in this example):
using Distributions
tpl = "Beta distribution with alpha={{α}}, beta={{β}}"
Mustache.render(tpl, Beta(1, 2))
"Beta distribution with alpha=1.0, beta=2.0"
Further, keyword arguments can be used when the variables in the templates are symbols:
goes_together = mt"{{{:x}}} and {{{:y}}}."
Mustache.render(goes_together; x="Salt", y="pepper")
Mustache.render(goes_together; x="Bread", y="butter")
"Bread and butter."
Multiple views#
Support for more than one view is also provided. A simple example with two named tuples is:
tpl = mt"""{{:a}} {{:b}} {{:c}}"""
tpl((;a=1, b=2), (;c=3))
"1 2 3"
When competing views specify the same value, the resolution comes from left to right with keyword arguments overriding any positional argument:
tpl((;a=1, b=2, c=4), (;c=3)), tpl((;a=1, b=2, c=4), (;c=3); c=5)
("1 2 4", "1 2 5")
Templates and tokens#
A template is parsed into tokens.
Parsing is done at compile time, if the
mtstring literal is used to define the template. If re-using a template, this is encouraged, as it will be more performant.
mt"""
{{:x}} is {{:y}}
"""
MustacheTokens
Mustache.TextToken("text", "")
Mustache.TagToken("name", ":x", "{{", "}}", "")
Mustache.TextToken("text", " is ")
Mustache.TagToken("name", ":y", "{{", "}}", "")
Mustache.TextToken("text", "\n")
If string interpolation is desired prior to the parsing into tokens, the
jmtstring literal can be used.
x = "John"
jmt"""
$x is {{:y}}
"""
MustacheTokens
Mustache.TextToken("text", "John is ")
Mustache.TagToken("name", ":y", "{{", "}}", "")
Mustache.TextToken("text", "\n")
(This can prove useful if two passes through a template are needed.)
As well, a string can be used to define a template. When
parseis called, the string will be parsed into tokens. This is the flow ifrenderis called on a string (and not tokens).
Tags#
A template use tags to specify areas to be filled in by a view. There are numerous tag types, summarized in a table near the end of this document.
Variables#
Tags representing variables for substitution have the form {{varname}}, {{:symbol}}, or their triple-braced versions {{{varname}}} or {{{:symbol}}}.
The varname version will match variables in a view such as a dictionary or a module.
The :symbol version will match variables passed in via named tuple or keyword arguments; also dictionaries with symbols for keys.
b = "be"
Mustache.render(mt"a {{b}} c", Main) # "a be c"
Mustache.render(mt"a {{:b}} c", b="bee") # "a bee c"
Mustache.render(mt"a {{:b}} c", (b="bee", c="sea")) # "a bee c"
"a bee c"
The triple brace prevents HTML substitution for entities such as <. The following are escaped when only double braces are used: "&", "<", ">", "'", "\", and "/".
Mustache.render(mt"a {{:b}} c", b = "%< bee >%") # "a %< bee >% c"
Mustache.render(mt"a {{{:b}}} c", b = "%< bee >%") # "a %< bee >% c"
"a %< bee >% c"
If different tags are specified to parse, say << or >>, then <<{ and }>> indicate the prevention of substitution.
tokens = Mustache.parse("a <<:b>> c", ("<<", ">>"))
Mustache.render(tokens, b = "%< B >%") # a %< B >% c"
tokens = Mustache.parse("a <<{:b}>> c", ("<<", ">>"))
Mustache.render(tokens, b = "%< B >%") # "a %< B >% c"
"a %< B >% c"
If the variable refers to a function, the value will be the result of calling the function with no arguments passed in.
Mustache.render(mt"a {{:b}} c", b = () -> "Bea") # "a Bea c"
"a Bea c"
using Dates
Mustache.render(mt"Written in the year {{:yr}}."; yr = year∘now) # "Written in the year 2023."
"Written in the year 2026."
Filtering#
This isn't part of the Mustache spec, but a filter can be applied to the value after it is looked up and before it is rendered. The tag syntax uses Julia's pipe operator, as in {{:varname |> functionname}}. The named function is looked up in the same view (or Main, then Base if not found) and is called with the resolved value.
Mustache.render(mt"Hello {{:name |> uppercase}}!", name="world", uppercase=uppercase)
"Hello WORLD!"
Inline anonymous functions are accepted too:
Mustache.render(mt"Hello {{:name |> x -> uppercase(x)}}!", name="world")
"Hello WORLD!"
A filter can be passed through the view if that flexibility is needed:
tpl = mt"Hello {{:name |> λ}}"
tpl(; name="world", λ=uppercase)
"Hello WORLD"
If this package is called from within a module, it might be necessary to pass in @__MODULE__ to the render function if a filter is defined within the current module.
Sections#
In the main example, the template included:
{{#in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/in_ca}}
Tags beginning with #varname and closed with /varname create "sections." These have different behaviors depending on the value of the variable.
The syntax {{#varname |> f}} applies the function f to the looked up value of varname before applying the section logic.
Using a true(ish) value to conditionally display a section#
When the variable is not a function or a container the part between them is used only if the variable is defined and not "falsy:"
a = mt"{{#:b}}Hi{{/:b}}";
a(; b=true) # "Hi"
a(; c=true) # ""
a(; b=false) # "" also, as `b` is "falsy" (e.g., false, nothing, "")
""
The Mustache spec call itself "logicless" but using a filter can add logic. For example this pattern will only show the value of x if x is a number:
tpl = mt"{{# :x |> r -> isa(r, Number)}}{{:x}}{{/ :x}}"
tpl(; x = "one"), tpl(;, x=1)
Inverted section tags#
Related, if the tag begins with ^varname and ends with /varname the text between these tags is included only if the variable is not defined or is falsy.
Inverted tags may have a function call on the looked up value through the syntax {{^varname |> f}}.
This example will show only one of the statements:
tpl = mt"""
{{#:x |> >=(10)}} bigger than or equal 10 {{/:x}}
{{^:x |> >=(10)}} less than 10 {{/:x}}
"""
tpl(; x = 5) |> print
less than 10
Using a function to modify the string within a section#
If the variable name refers to a function that function will be passed the unevaluated string within the section, as expected by the Mustache specification:
Mustache.render("{{#:a}}one{{/:a}}", a=length) # "3"
"3"
The specification has been widened to accept functions of two arguments, the string and a render function:
tpl = mt"{{#:bold}}Hi {{:name}}.{{/:bold}}"
function bold(text, render)
"<b>" * render(text) * "</b>"
end
tpl(; name="Tater", bold=bold) # "<b>Hi Tater.</b>"
"<b>Hi Tater.</b>"
If the tag "|" is used, the section value will be rendered first, an enhancement to the specification.
fmt(txt) = "<b>" * string(round(parse(Float64, txt), digits=2)) * "</b>";
tpl = """{{|:lambda}}{{:value}}{{/:lambda}} dollars.""";
Mustache.render(tpl, value=1.23456789, lambda=fmt) # "<b>1.23</b> dollars."
"<b>1.23</b> dollars."
(Without the | in the tag, an error, ERROR: ArgumentError: cannot parse "{{:value}}" as Float64, will be thrown.)
Iteration in a section#
If the section variable, {{#varname}}, binds to an iterable collection, then the text in the section is repeated for each item in the collection with the view used for the context of the template given by the item.
This is useful for collections of named objects, such as DataFrames (where the collection is comprised of rows) or arrays of dictionaries. For Tables.jl objects the rows are iterated over.
Iterating over vectors#
Iterating over a associative array, like a dictionary or named tuple, the keys are used as variable name. Though it isn't part of the Mustache specification, when iterating over a vector or tuple—which have no obvious key save for index—Mustache.jl uses {{.}} to refer to the item:
tpl = mt"{{#:vec}}{{.}} {{/:vec}}"
Mustache.render(tpl, vec = ["A1", "B2", "C3"]) # "A1 B2 C3 "
"A1 B2 C3 "
Note the extra space after C3.
There is also limited support for indexing with the iteration of a vector that allows one to treat the last element differently. The syntax .[ind] refers to the value vec[ind]. (There is no support for the usual arithmetic on indices.)
To print commas one can use this pattern:
tpl = mt"{{#:vec}}{{.}}{{^.[end]}}, {{/.[end]}}{{/:vec}}"
Mustache.render(tpl, vec = ["A1", "B2", "C3"]) # "A1, B2, C3"
"A1, B2, C3"
To put the first value in bold, but no others, say:
tpl = mt"""
{{#:vec}}
{{#.[1]}}<bold>{{.}}</bold>{{/.[1]}}
{{^.[1]}}{{.}}{{/.[1]}}
{{/:vec}}
"""
Mustache.render(tpl, vec = ["A1", "B2", "C3"]) # basically "<bold>A1</bold>B2 C3"
"<bold>A1</bold>\n\n\nB2\n\nC3\n"
This was inspired by this question, but the syntax chosen was more Julian. This syntax – as implemented for now – does not allow for iteration. That is constructs like {{#.[1]}} don't introduce iteration, but only offer a conditional check.
Iterating over DataFrames or other Tables compatible objects#
For data frames, the rows are iterated over. Data frames in Julia have named columns, not rows. Here is a template for making a markdown table from a data frame. The first line shows a filter applied to an iterable in a section tag. The second line shows function application to a variable. The rest shows nested iteration over unnamed elements.
tpl = mt"""
|{{#:d |> names}} {{.}} | {{/:d}}
|{{:d |> r -> ":----|" ^ size(r,2)}}
{{#:d}}
|{{#.}}{{.}}|{{/.}}
{{/:d}}
: {{:TITLE}}
"""
MustacheTokens
Mustache.TextToken("text", "|")
SectionToken("#", ":d |> names", "{{", "}}")
Mustache.TextToken("text", " ")
Mustache.TagToken("name", ".", "{{", "}}", "")
Mustache.TextToken("text", " | ")
Mustache.TextToken("text", "\n|")
Mustache.TagToken("name", ":d |> r -> \":----|\" ^ size(r,2)", "{{", "}}", "")
Mustache.TextToken("text", "\n")
SectionToken("#", ":d", "{{", "}}")
Mustache.TextToken("text", "|")
SectionToken("#", ".", "{{", "}}")
Mustache.TextToken("text", "")
Mustache.TagToken("name", ".", "{{", "}}", "")
Mustache.TextToken("text", "|")
Mustache.TagToken("/", ".", "{{", "}}", "")
Mustache.TextToken("text", "\n")
Mustache.TextToken("text", ": ")
Mustache.TagToken("name", ":TITLE", "{{", "}}", "")
Mustache.TextToken("text", "\n")
We illustrate on some synthetic data.
using DataFrames
d = DataFrame(names=["John", "Paul", "George", "Ringo"], hand=["right", "left", "right", "right"])
tpl(; d, TITLE="dominant hand") |> print
This can be compared to using an array of Dicts, convenient if you have data by the row:
A = [Dict("a" => "eh", "b" => "bee"),
Dict("a" => "ah", "b" => "buh")]
tpl = mt"{{#:A}}Pronounce a as {{a}} and b as {{b}}. {{/:A}}"
Mustache.render(tpl, A=A) |> print
Pronounce a as eh and b as bee. Pronounce a as ah and b as buh.
Iterating when the value of a section variable is a function#
From the Mustache documentation, consider the template
tpl = mt"""{{#:beatles}}
* {{:makename}}
{{/:beatles}}
"""
MustacheTokens
Mustache.TextToken("text", "")
SectionToken("#", ":beatles", "{{", "}}")
Mustache.TextToken("text", "* ")
Mustache.TagToken("name", ":makename", "{{", "}}", "")
Mustache.TextToken("text", "\n")
when beatles is a vector of named tuples (or some other Tables.jl object) and name is a function.
When iterating over beatles, name can reference the rows of the beatles object by name. In JavaScript, this is done with this.XXX. In Julia, the values are stored in the task_local_storage object (with symbols as keys) allowing the access. The Mustache.get_this function allows JavaScript-like usage:
function makename()
this = Mustache.get_this()
this.first * " " * this.last
end
beatles = [(first="John", last="Lennon"), (first="Paul", last="McCartney")]
tpl(; beatles, makename) |> print
* John Lennon
* Paul McCartney
Using a filter, this might be more explicitly done through:
mname(r) = r.first * " " * r.last
tpl = mt"""
{{# :beatles }}
* {{. |> mname }}
{{/ :beatles }}
"""
tpl(@__MODULE__; beatles) |> print # pass module to lookup `mname` within
* John Lennon
* Paul McCartney
Conditional checking without iteration#
The section tag, #, checks for existence; pushes the object into the view; and then iterates over the object. For cases where iteration is not desirable; the tag type @ can be used.
Compare these:
struct RANGE
range
end
tpl = mt"""
<input type="range" {{@:range}} min="{{start}}" step="{{step}}" max="{{stop}}" {{/:range}}>
""";
Mustache.render(tpl, RANGE(1:1:2))
tpl = mt"""
<input type="range" {{#:range}} min="{{start}}" step="{{step}}" max="{{stop}}" {{/:range}}>
""";
Mustache.render(tpl, RANGE(1:1:2)) # iterates over Range.range
"<input type=\"range\" min=\"1\" step=\"1\" max=\"2\" min=\"1\" step=\"1\" max=\"2\" >\n"
Additional features#
Non-eager finding of values#
A view might have more than one variable bound to a symbol. The first one found is replaced in the template unless the variable is prefaced with ~. This example illustrates:
d = Dict(:two=>Dict(:x=>3), :x=>2)
tpl = mt"""
{{#:one}}
{{#:two}}
{{~:x}}
{{/:two}}
{{/:one}}
"""
Mustache.render(tpl, one=d) # "2\n"
Mustache.render(tpl, one=d, x=1) # "1\n"
"1\n"
Were {{:x}} used, the value 3 would have been found within the dictionary Dict(:x=>3); however, the presence of {{~:x}} is an instruction to keep looking up in the specified view to find other values, and use the last one found to substitute in. (This is hinted at in this issue)
Partials#
Partials are used to include partial templates into a template.
Partials begin with a greater than sign, like {{> box.tpl }}. In this example, the file box.tpl is opened and inserted into the template, then populated. A full path may be specified.
They also inherit the calling context.
In this way you may want to think of partials as includes, imports, template expansion, nested templates, or subtemplates, even though those aren't literally the case here.
The partial specified by {{< box.tpl }} is not parsed, rather included as is into the file. This can be faster.
The variable can be a filename, as indicated above, or if not a variable. For example
tpl = """\"{{>partial}}\""""
Mustache.render(tpl, Dict("partial"=>"*{{text}}*","text"=>"content"))
"\"*content*\""
Summary of tags#
To summarize the different tags marking a variable or container:
{{variable}}does substitution of the value held invariablein the current view; escapes HTML characters. The double braces can be adjusted usingMustache.parse.{{{variable}}}does substitution of the value held invariablein the current view; does not escape HTML characters. The outer pair of mustache braces can be adjusted usingMustache.parse.{{&variable}}is an alternative syntax for triple braces (useful with custom braces){{~variable}}does substitution of the value held invariablein the outmost view{{#variable}}is section syntax. Sections are closed by{{/variable}}. Depending on the type of variable, it specifies the following:if
variableis not a container or a function and is not absent ornothingwill use the text between the matching tags, marked with{{/variable}}; otherwise that text will be skipped. (Like anif/endblock.)if
variableis a function, it will be applied to contents of the section. Use of|instead of#will instruct the rendering of the contents before applying the function. The spec allows for a function to have signature(x, render)whererenderis used internally to convert. This implementation allows rendering when(x)is the single argument.if
variableis aTables.jlcompatible object (row wise, with named rows), will iterate over the values, pushing the named tuple to be the top-most view for the part of the template up to{{\variable}}.if
variableis a vector or tuple—for the part of the template up to{{\variable}}—will iterate over the values. Use{{.}}to refer to the (unnamed) values. The values.[end]and.[i], for a numeric literal, will refer to values in the vector or tuple. For tabular data,{{.}}can also be iterated over.
{{^variable}}/{{.variable}}tags will show the values whenvariableis not defined, or isnothing.{{>partial}}will include the partial value into the template, filling in the template using the current view. The partial can be a variable or a filename (checked withisfile).{{<partial}}directly include partial value into template without filling in with the current view.{{!comment}}comments begin with a bang,!
Alternatives#
Julia provides some alternatives to this package which are better suited for many jobs:
For simple substitution inside a string there is string interpolation.
For piecing together pieces of text either the
stringfunction or string concatenation (the*operator) are useful. (Also anIOBufferis useful for larger tasks of this type.)For formatting numbers and text, the Formatting.jl package, the Format package, and the StringLiterals package are available.
The HypertextLiteral package is useful when interpolating HTML, SVG, or SGML tagged content.
Differences from Mustache.js#
This project deviates from Mustache.js in a few significant ways:
Julia structures are used, not JavaScript objects. As illustrated, one can use Dicts, Modules, DataFrames, functions, ...
In the Mustache spec, when lambdas are used as section names, the function is passed the unevaluated section:
template = "<{{#lambda}}{{x}}{{/lambda}}>"
data = Dict("x" => "Error!", "lambda" => (txt) -> txt == "{{x}}" ? "yes" : "no")
Mustache.render(template, data) ## "<yes>", as txt == "{{x}}"
"<yes>"
The tag "|" is similar to the section tag "#", but will receive the evaluated section:
template = "<{{|lambda}}{{x}}{{/lambda}}>"
data = Dict("x" => "Error!", "lambda" => (txt) -> txt == "{{x}}" ? "yes" : "no")
Mustache.render(template, data) ## "<no>", as "Error!" != "{{x}}"
"<no>"
Tags referencing variables can have a filter applied:
tpl = mt"""
{{:x}} --> {{:x |> uppercasefirst}} --> {{:x |> x-> uppercase(x[1:2]) * x[3:end]}} --> {{:x |> uppercase}}
"""
tpl(; x = "boo") |> print
boo --> Boo --> BOo --> BOO
API#
Mustache.Mustache
source
Mustache
Mustache is a templating package for Julia based on Mustache.js. [ Docs ]
Mustache.load — Tuple{AbstractString, Vararg{Any}}
source
Mustache.load(filepath, args...)
Load file specified through filepath and return the compiled tokens. Tokens are memoized for efficiency,
Additional arguments are passed to Mustache.parse (for adjusting the tags).
Mustache.parse — Union{Tuple{Any}, Tuple{Any, Any}}
source
Mustache.parse(template, tags = ("{{", "}}"))
Parse a template into tokens.
template: a string containing a templatetags: the tags used to indicate a variable. Adding interior braces ({,}) around the variable will prevent HTML escaping. (That is for the default tags,{{{varname}}}is used; for tags like("<<",">>")then<<{varname}>>is used.)
Extended
The template interprets tags in different ways. The string macro mt is used below to both parse (on construction) and render (when called).
Variable substitution.
Like basic string interpolation, variable substitution can be performed using a non-prefixed tag:
julia> using Mustache
julia> a = mt"Some {{:variable}}.";
julia> a(; variable="pig")
"Some pig."
julia> a = mt"Cut: {{{:scissors}}}";
julia> a(; scissors = "8< ... >8")
"Cut: 8< ... >8"
Both using a symbol, as the values to substitute are passed through keyword arguments. The latter uses triple braces to inhibit the escaping of HTML entities.
Tags can be given special meanings through prefixes. For example, to avoid the HTML escaping an & can be used:
julia> a = mt"Cut: {{&:scissors}}";
julia> a(; scissors = "8< ... >8")
"Cut: 8< ... >8"
Sections
Tags can create "sections" which can be used to conditionally include text, apply a function to text, or iterate over the values passed to render.
Include text
To include text, the # prefix can open a section followed by a / to close the section:
julia> a = mt"I see a {{#:ghost}}ghost{{/:ghost}}";
julia> a(; ghost=true)
"I see a ghost"
julia> a(; ghost=false)
"I see a "
The latter is to illustrate that if the variable does not exist or is "falsy", the section text will not display.
The ^ prefix shows text when the variable is not present.
julia> a = mt"I see {{#:ghost}}a ghost{{/:ghost}}{{^:ghost}}nothing{{/:ghost}}";
julia> a(; ghost=false)
"I see nothing"
Apply a function to the text
If the variable refers to a function, it will be applied to the text within the section:
julia> a = mt"{{#:fn}}How many letters{{/:fn}}";
julia> a(; fn=length)
"16"
The use of the prefix ! will first render the text in the section, then apply the function:
julia> a = mt"The word '{{:variable}}' has {{|:fn}}{{:variable}}{{/:fn}} letters.";
julia> a(; variable="length", fn=length)
"The word 'length' has 6 letters."
Variable tags may also apply a post-lookup function with |>:
julia> a = mt"Hello {{:name |> uppercase}}!";
julia> a(; name="world", uppercase=uppercase)
"Hello WORLD!"
This also works for section and inverted-section tags, applying the function before truthiness or iteration is decided.
Anonymous functions are also accepted:
julia> a = mt"Hello {{:name |> x -> uppercase(x)}}!";
julia> a(; name="world")
"Hello WORLD!"
Iterate over values
If the variable in a section is an iterable container, the values will be iterated over. Tables.jl compatible values are iterated in a row by row manner, such as this view, which is a tuple of named tuples:
julia> a = mt"{{#:data}}x={{:x}}, y={{:y}} ... {{/:data}}";
julia> a(; data=((x=1,y=2), (x=2, y=4)))
"x=1, y=2 ... x=2, y=4 ... "
Iterables like vectors, tuples, or ranges – which have no named values – can have their values referenced by a {{.}} tag:
julia> a = mt"{{#:countdown}}{{.}} ... {{/:countdown}} blastoff";
julia> a(; countdown = 5:-1:1)
"5 ... 4 ... 3 ... 2 ... 1 ... blastoff"
Partials
Partials allow substitution. The use of the tag prefix > includes either a file or a string and renders it accordingly:
julia> a = mt"{{>:partial}}";
julia> a(; partial="variable is {{:variable}}", variable=42)
"variable is 42"
The use of the tag prefix < just includes the partial (a file in this case) without rendering.
Comments
Using the tag-prefix ! will comment out the text:
julia> a = mt"{{! ignore this comment}}This is rendered";
julia> a()
"This is rendered"
Multi-lne comments are permitted.
Mustache.render — Tuple{IO, Mustache.MustacheTokens, Vararg{Any}}
source
render([io], tokens, view)
render([io], tokens; kwargs...)
(tokens::MustacheTokens)([io]; kwargs...)
Render a set of tokens with a view, using optional io object to print or store.
Arguments
io::IO: OptionalIOobject.tokens: Either Mustache tokens, or a string to parse into tokensview: A view provides a context to look up unresolved symbols demarcated by mustache braces. A view may be specified by a dictionary, a module, a composite type, a vector, a named tuple, a data frame, aTablesobject, or keyword arguments.
Note
The render method is currently exported, but this export may be deprecated in the future.
Mustache.render_from_file — Tuple{AbstractString, Any}
source
render_from_file(filepath, view)
render_from_file(filepath; kwargs...)
Renders a template from filepath and view.
Note
This function simply combines Mustache.render and Mustache.load and may be deprecated in the future.
Mustache.@jmt_str — Tuple{String}
source
jmt"string"
String macro that interpolates values escaped by dollar signs, then parses strings.
Note: very lightly modified from a macro in HypertextLiteral.
Example:
x = 1
toks = jmt"$(2x) by {{:a}}"
toks(; a=2) # "2 by 2"