UNPKG

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
<!DOCTYPE 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> ```