create-modulo
Version:
Starter projects for Modulo.html - Ready for all uses - Markdown-SSG / SSR / API-backed SPA
864 lines (656 loc) • 21.7 kB
HTML
<meta charset=utf8><script src=../static/Modulo.html></script><script type=md>---
title: Template Filters
---
This document lists and shows examples for each of the the built-in Template
Filters that are already registered with Modulo template system.
# Template Filters
## add
Adds the argument to the value. Example:
```modulo
edit: demo=modulo
<Template>
{{ state.value|add:7 }} hacks <br />
{{ state.value|add:state.another }} hz
</Template>
<State
value:=1330
another:=1270
></State>
```
## allow
Given an "allowed list" of comma separated strings, only permit values that
exist exactly the "allowed list". If the value does not exist within the
allowed list, it will produce an empty string (`""`). The fact that empty
strings are "falsy" means you can chain together this filter with the default
filter in order to provide a fallback as well, which is demonstrated in the
third example. Examples:
*Note:* You should not use this for input validation for security purposes (use
the backend instead, since any frontend code can be altered by users) or input
validation, for which you use should `pattern=` instead since it's built in to
HTML.
```modulo
edit: demo=modulo
<Template>
Valid: {{ state.value|allow:"orange,apple,pear" }} <br />
Invalid: {{ state.value|allow:"a,b,c" }} <br />
Invalid + default: {{ state.value|allow:"a,b,c"|default:"Oops!" }}
</Template>
<State
value="apple"
></State>
```
## camelcase
Converts a `kebab-case-style-string` (like favored by HTML, or website URL
slugs), among other formats, into a `camelCase` (like what's favored by
JavaScript, others).
```modulo
edit: demo=modulo
<Template>
Original: {{ state.slug }} <br />
Camel: {{ state.slug|camelcase }} <hr />
Original: {{ state.filename }} <br />
Camel: {{ state.filename|camelcase }}
</Template>
<State
slug="no-more-sluggish-sites"
filename="article-dir-index_2.html"
></State>
```
## capfirst
Output given string with the first letter capitalized.
```modulo
edit: demo=modulo
<Template>
The {{ state.value|capfirst }} framework is my favorite
</Template>
<State
value="modulo.html"
></State>
```
## combine
Combine is for combining values, which results in a few different operations
depending on type. For Arrays, it will combine them end-to-end. For Objects, it
will attempt to "squash" them. See the following examples:
```modulo
edit: demo=modulo
<Template>
Arrays: {{ state.start|combine:state.end|json }}<br />
Objects: {{ state.baseobj|combine:state.topobj|json }}
</Template>
<State
start:='[ 1, 2, 3 ]'
end:='[ "a", "b", "c" ]'
baseobj:='{ "a": 1, "b": 2 }'
topobj:='{ "b": 3, "c": 4 }'
></State>
```
## default
If the given value is [Falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), use the given default. Otherwise, use the value.
```modulo
edit: demo=modulo
<Template>
Fave snack: {{ state.snack|default:"icecream" }} <br />
Snack count: {{ state.count|default:"none" }} <br />
Fave soda: {{ state.soda|default:"Cola" }}
</Template>
<State
snack=""
count:=0
soda="guarana"
></State>
```
## divisibleby
Returns `true` if the value is evenly divisible by the given argument.
```modulo
edit: demo=modulo
<Template>
Can {{ state.value }} divide by 3? <br />
{{ state.value|divisibleby:3 }} <br />
{% if state.value|divisibleby:2 %}
{{ state.value }} is even
{% endif %}
</Template>
<State
value:=4
></State>
```
## entries
Convert the entire Object an Array format. If you only want one part of it, see
the related [values](#values) and [keys](#keys).
```modulo
edit: demo=modulo
<Template>
Entries: {{ state.obj|entries|json }}
</Template>
<State
obj:='{
"abc": 123,
"def": 456
}'
></State>
```
## escapejs
Escape special characters in a given string using JavaScript (specifically,
JSON) escaping rules. If you have a string like `"Hello\nWorld!"` (where `\n`
is a single new-line character), it will output `Hello\nWorld!` (that is, as
"backslash-n" or two characters). It will also "double-up" any backslashes it
encounters.
```modulo
edit: demo=modulo
<Template>
Result: {{ state.value|escapejs }} <br />
</Template>
<State
value="Just
trying
\stuff\
out"
></State>
```
## first
Retrieve the first item in an Array:
<!--Note that it's the opposite of [#skipfirst]. This means by combining these two filters, you can slice up your data for either displaying tables (as shown with the [#skipfirst] example), or even combine both on the same data to select. Tip for SQL developers: `LIMIT` and `OFFSET` correspond in behavior to `|first` and `|skipfirst`.-->
<!--TODO: Need to implement argument to make it symetrical, along with "last" <p>Top two: {{ state.cities|first:2 }}</p>-->
```modulo
edit: demo=modulo
<Template>
<p>Biggest city: {{ state.cities|first }}</p>
</Template>
<State
cities:='[ "Montevideo", "Salto", "Rocha", "Chuy" ]'
></State>
```
## get
The "get" filter is very versatile. It's used for traversing complex data
structures to retrieve values based on given "property path", or access
properties based on the value of variables. Note that for _Array_ types, it
will use JavaScript logic of starting counting at 0 (e.g. counting index as 0,
1, 2 ... ). Also note that it treats _Array_ and _Object_ types interchangeably:
You can use dot (`.`) notation for either.
The following demonstrates 3 uses:
```modulo
edit: demo=modulo
<Template>
<p>Basic: {{ state.cities|get:2 }}</p>
<p>Another variable: {{ state.cities|get:state.my-num }}</p>
<p>Drill down: {{ state.complex-data|get:'a.b.c.2' }}</p>
</Template>
<State
my-num:=3
cities:='[ "Oakland", "Berkeley", "Richmond", "Concord" ]'
complex-data:='{ "a": { "b": { "c": [ "x", "y", "z" ] } } }'
></State>
```
## join
Formats an array to be comma-separated. Optionally, a different separator can be specified as an argument.
```modulo
edit: demo=modulo
<Template>
<p>{{ state.athletes|join }}</p>
<p>{{ state.athletes|join:" + " }}</p>
</Template>
<State
athletes:='[ "Gustavo Goodman", "Zoey Zaïre" ]'
></State>
```
## json
Formats given data as a JSON string. It takes one optional argument, that if specified, will cause indentation by the given amount.
```modulo
edit: demo=modulo
<Template>
<pre>{{ state.athletes|json }}</pre>
<pre>{{ state.athletes|json:2 }}</pre>
</Template>
<State
athletes:='[
{ "name": "Gus", "sport": "Pickleball" },
{ "name": "Zoe" },
{ "name": "Mahmoud "}
]'
></State>
<Style>
:host {
overflow: auto;
display: block;
height: 180px;
}
</Style>
```
## keys
Show only the keys of the given Object, converted into an Array format. See
also the similar [values](#values) and [entries](#entries).
```modulo
edit: demo=modulo
<Template>
Keys: {{ state.obj|keys|json }}
</Template>
<State
obj:='{
"abc": 123,
"def": 456
}'
></State>
```
## last
Retrieve the last item in an Array:
```modulo
edit: demo=modulo
<Template>
<p>{{ state.sports|last }}</p>
</Template>
<State
sports:='[ "Pickleball", "Footvolley", "Beach Volleyball" ]'
></State>
```
## length
Determine the length of the given value. This supports Strings, Arrays, and Objects. For Objects, it will return the number of properties on the object.
```modulo
edit: demo=modulo
<Template>
<p>Sentence length: {{ state.sentence|length }}</p>
<p>Flowers length: {{ state.flowers|length }}</p>
<p>Flights length: {{ state.flights|length }}</p>
</Template>
<State
sentence="The sweat wis lashing oafay Sick Boy; he wis trembling."
flowers:='[ "Marigolds", "Sunflowers" ]'
flights:='{ "SFO": "LAX", "BAI": "MEX", "MEX": "MVD" }'
></State>
```
## lower
Display the given string in all lowercase letters.
```modulo
edit: demo=modulo
<Template>
<p>Without: {{ state.word }}</p>
<p>Lower: {{ state.word|lower }}</p>
</Template>
<State
word="rAndOm cAPitalS"
></State>
```
## multiply
Performs the mathematical operation of "multiplication" of the given numbers.
```modulo
edit: demo=modulo
<Template>
{{ state.a }} x {{ state.b }} =
{{ state.a|multiply:state.b }}
</Template>
<State
a:=10
b:=3
></State>
```
## number
Converts a String type to a Number type, so numeric comparisons can be made.
Otherwise, the String type will default to alphabetically comparisons and
operations.
See below for an example of using it to force numeric operations. In this
example it's necessary since "5" comes after "1" alphabetically (e.g. just as
`"Jo"` comes after `"Anderson"` alphabetically, despite `"Jo"` being shorter,
"50" comes after "1000", even if, when read numerically, `1000` is greater than
`50`).
```modulo
edit: demo=modulo
<Template>
{% if state.a gt state.b %} A is greater than B alphabetically
{% else %}B is greater than A alphabetically {% endif %}
<p><em>However...</em></p>
{% if state.a|number gt state.b|number %} A is greater than B numerically
{% else %}B is greater than A numerically {% endif %}
</Template>
<State
a="1000"
b="50"
></State>
```
<!--
## pluralize
Allows for convenient pluralization in many human languages. This is for words
in languages where a plural form is used when there is "0" or "2+" items, and a
singular form for exactly 1 item. This is useful for the majority of noun and
verb conjugations in English, along with many other Indo-European languages.
To use, give it a number (typically, the length of a list), and a comma
separated version of two forms of a word. If that number is exactly "1" it will
output the second form (or nothing at all, if the second form is not
specified), otherwise it will output the first form.
Below are some examples. Note that in the second example, it does not specify a
singular form, but instead only specifies an "s" to append to the word "flower"
to make it's plural "flowers".
```modulo
edit: demo=modulo
<Template>
We visited {{ state.citynames|length}}
{{ state.citynames|length|pluralize:"cities,city" }}
and picked {{ state.flowers|length}}
flower{{ state.flowers|length|pluralize:"s" }}
</Template>
<State
flowers:='["Marigolds", "Sunflowers"]'
citynames:='["Oakland", "Berkeley", "Richmond", "Concord"]'
></State>
```
-->
## safe
By default, template variables automatically escape the output of every
variable value. Specifically, `>`, `<`, `'`, `"`, and `&` are all turned into
their "escaped" HTML equivalents, to prevent them from being interpreated as
HTML tags.
`|safe` disables this feature. It "marks" the HTML as "safe" for inclusion, and
thus allowed to be interpreted as HTML, and not just display the sourcecode to
the user. Further reading on this topic is in the
[Templating section on "Escaping"](/docs/templating/#escaping).
See below for example:
```modulo
edit: demo=modulo
<Template>
Escaped: {{ state.str }}<br />
Marked safe: {{ state.str|safe }}
</Template>
<State
str="Try to escape <em>this!</em>"
></State>
```
## skipfirst
Takes all except for the first element. It's useful for skipping over data you
don't need to process. You can skip more than one by specifying the optional
argument. For example, "`|skipfirst:10`" will cause
it to "skip the first 10".
Note that it's the opposite of [|first](#first). This means by combining these
two filters, you can slice up your data for either displaying tables (as shown
below), or even combine both on the same data to select. Tip for SQL
developers: `LIMIT` and `OFFSET` correspond in behavior to `|first` and
`|skipfirst`.
```modulo
edit: demo=modulo
<Template>
{% for top in state.data|first %} <h5>{{ top }}</h5> {% endfor %}
{% for row in state.data|skipfirst %}
{% for cell in row %}
<div>{{ cell }}</div>
{% endfor %}
{% endfor %}
</Template>
<State
data:='[
[ "Col 1", "Col 2", "Col 3" ],
[ 1, 2, 3 ],
[ 1, 2, 3 ],
[ 1, 2, 3 ]
]'
></State>
<Style>
:host {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
</Style>
```
## sorted
Sorts the given array, possibly by an object key specified:
```modulo
edit: demo=modulo
<Template><pre>
Unsorted: {{ state.nums|join }} <br />
Sorted: {{ state.nums|sorted|join }} <br /> <br />
Sorted by "a": {{ state.objs|sorted:"a"|json }} <br />
by state.field: {{ state.objs|sorted:state.field|json }}
</pre></Template>
<State
nums:='[ 123, 93, 1, 34, 3, 9 ]'
objs:='[ { "a": 23, "b": "Al" }, { "a": 2, "b": "Zoe" } ]'
field="b"
></State>
```
## subtract
Subtracts the argument from the value. Example:
```modulo
edit: demo=modulo
<Template>
{{ state.value|subtract:3 }} hacks <br />
{{ state.value|subtract:state.another }} is the answer
</Template>
<State
value:=1340
another:=1298
></State>
```
## tagswap
Given a string of HTML code, this will transform that HTML code by doing a
simple find-and-replace operation, swapping one or more HTML tags for other
HTML tags. A few examples of uses: Applying to templates (e.g. see [renderas
filter](#renderas) below), making quick previews of user-inputted HTML by
substituting real HTML tags with components that generate previews, or
to get around limitations of HTML with how certain tags behave differently when
parsing (e.g. see how it's used in the
[`-filter-content`](/docs/processors.html#filtercontent) _Processor_ to more
conveniently construct `<table>` tags).
handles content in `<table>` and `<td>`
tags differently than other tags).
. The
result will be automatically marked as safe, since the only purpose of this tag
is to output HTML.
The argument can be in the format of a String (using `=` to indicate
substitution, separating each one by a space) or an Object. Examples of both
below:
```modulo
edit: demo=modulo
<Template>
<p>{{ state.html-code|tagswap:"a=del b=a" }}</p>
<p>{{ state.html-code|tagswap:state.tags }}</p>
</Template>
<State
html-code="<a>abc</a><b>123</b><A>def</a>"
tags:='{ "a": "del" }'
></State>
```
## trim
Trims away whitespace and other unwanted text from the start and/or end
of the given _String_. By default, it will only trim whitespace, but if given
an argument, it will attempt to remove both whitespace, and what is specified,
with a comma to separate beginning or end of the string. Example:
```modulo
edit: demo=modulo
<Template>
<pre>Without: {{ state.country }}</pre>
<pre>Default: {{ state.country|trim }}</pre>
<pre>Extras: {{ state.country|trim:'[,]()' }}</pre>
</Template>
<State
country="
[Türkiye]() "
></State>
```
## truncate
Cut off the given string after a number of characters specified by the argument. If it has to cut off the string, it will append an "ellipsis" character.
```modulo
edit: demo=modulo
<Template>
<p>Long sentence: {{ state.sentence|truncate:20 }}</p>
<p>Short word: {{ state.word|truncate:20 }}</p>
</Template>
<State
sentence="The sweat wis lashing oafay Sick Boy; he wis trembling."
word="Bird."
></State>
```
## type
Attempts to figure out the JavaScript type of the given value, and returns the
type, in all lowercase. Useful for acting differently when data, for example,
is a Number, instead of a String.
```modulo
edit: demo=modulo
<Template>
{{ state.str|type }} <br />
{{ state.num|type }} <br />
{{ state.arr|type }} <br />
{{ state.obj|type }} <br />
{{ state.bool|type }} <br />
{{ state.arr.reverse|type }} <br />
{% if state.arr|type is "array" %}
<hr /> It's an array!
{% endif %}
</Template>
<State
str="abc"
num:=123
arr:='[ 1, 2, 3 ]'
obj:='{ "a": 3 }'
bool:=false
></State>
```
> **renderas Sandboxing** - Note that the child template will be isolated or
> "sandboxed" to _only_ have access to properties of the one, specified object,
> meaning no CParts (e.g. _state_, _props_, etc.) will be available, unless
> those are explicitly included in the specified object. This is to simplify
> the child templates. However, sometimes it is desirable for the child
> template to behave just like the parent so you can quickly split up
> templates. To simply include another template without any sandboxing, use the
> [include template-tag](/templating/tags.html).
## renderas
A highly useful filter that allows use of re-usable template snippets.
Typically in the format of `{{ state.data|renderas:trow }}`, where `state.data`
is some Object, and there exists a template like with the `-name` "trow" that
renders that object. The typical usage of this is to take complicated bits of
template code and refactor them into another smaller, more isolated, and less
complicated helper, "child" template, that are referenced within the main
template.
The "input" to renderas should always be an Object. The keys and values of that
object will populate the "template variables" for that template, meaning you
can access them directly as template variables within the child template. As an
example, if we `renderas` with an Object like `{ "myTitle": "Newest entry" }`,
then within the child template the "myTitle" becomes a "top-level" variable.
This means we can directly use syntax like `{{ myTitle }}` or `{{ my-title }}`
(no need for "." syntax). Example:
```modulo
edit: demo=modulo
<Template -name="trow">
<div><strong>{{ name }}</strong></div>
<div><em>{{ type }}</em></div>
<div><tt>{{ level }}</tt></div>
</Template>
<Template>
<section>
<h3>Name</h3> <h3>Type</h3> <h3>Level</h3>
{% for info in state.pokemon %}
{{ info|renderas:trow }}
{% endfor %}
</section>
</Template>
<State
pokemon:='[
{"name": "Jigglypuff", "type": "Normal", "level": 13},
{"name": "Pikachu", "type": "Electric", "level": 10},
{"name": "Ghastly", "type": "Ghost", "level": 8}
]'
></State>
<Style>
section {
display: grid;
grid-template-columns: 2fr 2fr 1fr;
}
</Style>
```
## reversed
Reverses the given input. Typically, this is used to reverse Arrays, such as
when you want to iterate over an Array in the opposite direction using
a `{% for %}` template-tag. If the input is a String or another data type, it
will attempt to first convert to an Array.
```modulo
edit: demo=modulo
<Template>
<p>{{ state.flowers|reversed|join }}</p>
{% for city in state.cities|reversed %}
<p>{{ city }}</p>
{% endfor %}
</Template>
<State
flowers:='[ "Marigolds", "Sunflowers" ]'
cities:='[ "Oakland", "Berkeley", "Richmond", "Concord" ]'
></State>
```
## upper
Display the given string in all uppercase letters.
```modulo
edit: demo=modulo
<Template>
<p>Without: {{ state.word }}</p>
<p>Upper: {{ state.word|upper }}</p>
</Template>
<State
word="rAndOm cAPitalS"
></State>
```
## values
Show only the values of the given Object, converted into an Array format. See
also the similar [keys](#keys) and [entries](#entries).
```modulo
edit: demo=modulo
<Template>
Values: {{ state.obj|values|json }}
</Template>
<State
obj:='{
"abc": 123,
"def": 456
}'
></State>
```
## yesno
The `|yesno` filter converts the data into a string. The `|yesno` filter is a
handy shortcut with many practical uses when generating HTML and displaying
values from the database.
### Typical usage
Without an argument, it will simply convert booleans to the words "yes" and
"no". When an argument is provided, this will be used instead, and can end up
being simpler than a full if statement. Examples of both below:
```modulo
edit: demo=modulo
<Template>
<input state.bind name="active" type="checkbox" />
<p class="{{ state.active|yesno:'p-act' }}">
Checked? {{ state.active|yesno }}
</p>
</Template>
<State
active:=null
></State>
<Style>
.p-act {
color: green;
}
</Style>
```
### All behavior options
By default, it will convert `true` and other true values into "yes", `false`
and other false values, and the "placeholder" `null` type into a "" (blank),
since that is often used to designate something that is not yet defined (such
as a null value in a database). When arguments are provided, these substitute
these 3 options, as designated by commas. If a single argument is provided,
then both "no" and "null" options get combined into "", and only "truthy"
values will cause the given argument to show. With two arguments, the default
behavior is replaced with the two alternaties. With 3 arguments, then a value
is presented for the undefined third value as well.
```modulo
edit: demo=modulo
<Template>
<span></span> <h3>{{ state.a }}</h3> <h3>{{ state.b }}</h3> <h3>{{ state.c }}</h3>
<span></span> <span>{{ state.a|yesno }}</span> <span>{{ state.b|yesno }}</span> <span>{{ state.c|yesno }}</span>
<span>on</span> <span>{{ state.a|yesno:"on" }}</span> <span>{{ state.b|yesno:"on" }}</span> <span>{{ state.c|yesno:"on" }}</span>
<span>on,off</span> <span>{{ state.a|yesno:"on,off" }}</span> <span>{{ state.b|yesno:"on,off" }}</span> <span>{{ state.c|yesno:"on,off" }}</span>
<span>on,off,maybe</span> <span>{{ state.a|yesno:"on,off,maybe" }}</span> <span>{{ state.b|yesno:"on,off,maybe" }}</span> <span>{{ state.c|yesno:"on,off,maybe" }}</span>
</Template>
<State
a:=true
b:=false
c:=null
></State>
<Style>
:host {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
text-align: right;
}
</Style>
```