Built-in Filters

Here are the filters available by default in Leanplum messaging:

abs

Return the absolute value of the argument.

{% set negativeNumber = -3 %}
{{ negativeNumber | abs }}

outputs: 3

add

Adds a number to the existing value.

{% set originalNumber = 7 %}
{{ originalNumber | add(3) }}

outputs: 10

attr

Renders the attribute of a dictionary.

{{ foo | attr(bar) }}

outputs the bar attribute

base64encode

'(string}'

Encodes the given UTF-8 string into Base64 format. Note that the encoding is not URL safe, so you can use the urlencode filter to do so.

{{ 'Some test string' | base64encode }}

outputs 'U29tZSB0ZXN0IHN0cmluZw=='

base64decode

'(string}'

Decodes the given Base64 string into UTF-8.

{{ 'U29tZSB0ZXN0IHN0cmluZw==' | base64decode }}

outputs 'Some test string'

batch

batch(count, fill_with)

Batches items into new list(s) of length count. If count is less than the length of the original list, it will be batched into multiple lists with a maximum length count (the last list may include less than count items). Set the optional fill_with text to fill in any missing items for the last list.

If given a list activities = ['hiking', 'swimming', 'cycling']:

  • {{ activities | batch(2) }} creates the list [ ['hiking', 'swimming' ], ['cycling'] ]
  • {{ activities | batch(2, 'filler') }} creates the list [ ['hiking', 'swimming' ], ['cycling', 'filler'] ]
  • {{ activities | batch(3) }} creates the list [ ['hiking', 'swimming', 'cycling'] ]
  • {{ activities | batch(5, 'blank') }} creates the list [ ['hiking', 'swimming', 'cycling', 'blank', 'blank']

If given a string, the string will be broken into lists of letters. For example, if given the string activites = hiking:

  • {{ activities | batch(2) }} creates the list [['h', 'i'], ['k', 'i'], ['n', 'g']]

You'll need to iterate through the new list(s) to output it into a message.

{% set activities = ['hiking', 'running', 'swimming'] %}
{% for item in activities | batch(5, ' ') %}
    <tr>
    {% for i in item %}
        <td>{{i}}</td>
    {% endfor %}
    </tr>
{% endfor %}

between_times

(end,'unit')

Calculates the time between two datetime objects.
end - Datetime object or timestamp at the end of the period. Required.
'unit' - Which temporal unit to use eg. 'hours', 'days', 'minutes' etc. Required.

{{today('UTC+5')|between_times(today(),'hours')}}

outputs: 5

capitalize

Capitalize a value. The first character in the string will be uppercase, all others lowercase.

{% set title = "my message" %}
{{ title | capitalize }}

outputs: "My message"

converttimezone

('timezone')

Returns the same moment of a datetime object, defined in the given Time Zone in ISO-8601 format. Returns null if the Time Zone cannot be parsed. Return type is datetime object

Current moment is 2021-02-18 23:10:39 UTC

{{ now() | converttimezone('PST') }}

outputs: 2021-02-18 15:10:39

{{ now() | converttimezone('+0200') }}

outputs: 2021-02-19 01:10:39

center

(width=80)

Uses whitespace to center the value in a field of a given width (defaults to 80).

{% set message = "my message" %}
{{ message | center(20) }}

outputs:
     my message

count

Alias of length.

cut

(to_remove)

Removes a string from the value from another string.

d

Alias of default.

date

Alias of datetimeformat.

datetimeformat

(format='%H:%M / %d-%m-%Y')

Formats a date object. For all possible options, check the official Python docs.

default

(default_value, boolean=False)

Returns the variable if defined, or the default_value if the variable is undefined. Set the second argument boolean to true if you want to use default for a variable that evaluates to false (like an empty string).

{% set homeCity = 'San Francisco' %}
{{ homeCity | default('Your city') }}

outputs: 'San Francisco'

{{ '' | default('the string was empty', true) }}

outputs: "the string was empty"

dictsort

(case_sensitive=False, by='key')

Sort a dictionary and yield (key, value) pairs. Set case_sensitive to true if you want to capital case to be considered and sorted first. Set by='value' to sort by the dictionary value.

{% set testDict = {'b': 'Aa', 'a': 'Ab', 'A': 'd'} %}

{{ testDict | dictsort }}

outputs: 
[('a', 'Ab'), ('A', 'd'), ('b', 'Aa')]

{{ testDict | dictsort(true) }}

outputs:
[('A', 'd'), ('a', 'Ab'), ('b', 'Aa')]

{{ testDict | dictsort(false, 'value') }}

outputs: 
[('b', 'Aa'), ('a', 'Ab'), ('A', 'd')]

You can use set to store and manipulate the dictionary, then iterate through the returned, sorted list.

{%- set orig = {'b': 'Aa', 'a': 'Ab', 'A': 'd'} -%}
{%- set test = orig | dictsort -%}
{%- for key, val in test -%}
  {{key}}: {{val}}
{% endfor -%}

outputs
a: Ab
A: d
b: Aa

divide

Divides the current value by a divisor.

{{ 9 | divide(3) }}

outputs 3

divisible

Evaluates to true if the value is divisible by the given number.

{{ 9 | divisible(3) }}

outputs true

e

Alias of escape.

escape

Converts the characters &, <, >, , and in strings to HTML-safe sequences. Use this filter if you need to display text that might contain such characters in HTML. Marks return value as markup string.

{% set html = '<p>This is a paragraph</p>' %}
{{ html | escape }}

outputs &lt;p&gt;This is a paragraph&lt;/p&gt;

filesizeformat

(binary=False)

Format the value into a ‘human-readable’ file size (i.e. 13 kB, 4.1 MB, 102 Bytes, etc). Set binary=True to use the binary prefixes.

{{ '3200' | filesizeformat }}

outputs 3.2kB

{{ '3200' | filesizeformat(true) }}

outputs 3.2KiB

first

Return the first item of a sequence.

{% set movieList = [{'title': 'The Big Lebowski'}, {'title': 'Fargo'}] %}
{% set firstMovie = movieList | first %}

sets firstMovie to {'title': 'The Big Lebowski'}

{{ firstMovie.title }}

outputs 'The Big Lebowski'

float

(default=0.0)

Convert a string value into a floating point number. If the conversion doesn't work, it will return the default value.

{{ '3' | float }}

outputs 3.0

{{ 'blah' | float(1.0) }}

outputs 1.0

forceescape

Enforce HTML escaping. This will probably double escape variables.

{{ '<a href="http://www.google.com>"google</a>' | forceescape }}

outputs &lt;a href=&#34;http://www.google.com&gt;&#34;google&lt;/a&gt;

groupby

(attribute)

Group a sequence of objects by a common attribute into a tuple of (key, list) where list includes the matching objects.

If you have a list of dictionaries with name and job properties, and you want to group them by job title, you can do the following:

{% set users = [
    {'name': 'Bob', 'job': 'Engineer'},
    {'name': 'Jane', 'job': 'Engineer'},
    {'name': 'Bob', 'job': 'Writer'}
] %}
{% set groupedList = users|groupby('name') %}

sets groupedList to:
[
  ('Engineer', [{'job': 'Engineer', 'name': 'Bob'}, {'job': 'Engineer', 'name':
  'Jane'}]), 
  ('Writer', [{'job': 'Writer', 'name': 'Bob'}])
]

indent

(width=4, indentFirst=false)

Uses whitespace to indent a string. Set width to the number of spaces to indent. Set indentFirst to true to indent the first line (not indented by default).

{% set test = 'This is the first line of multi-line text.

This second line will be indented two spaces.' %}
{{ test | indent(2) }}

outputs:
This is the first line of multi-line text.
  
  This second line will be indented two spaces.

int

(default=0)

Convert the value into an integer. If the conversion doesn’t work it will return the default 0. Override this by setting the default parameter to an integer.

🚧

String values with decimals

The value passed into the filter must have integer syntax already. If the value is a float / decimal syntax, i.e. '1.00', this will fail to convert, even though it is numerically equal to the integer 1.

If your values may have decimals, use the "float" filter instead, as this will accept both integer and float values.

{% set test = '1' %}
{{ test | int() }}

outputs 1

{% set test = '1.00' %}
{{ test | int() }}

outputs 0

{% set test = 'blah' %}
{{ test | int(2) }}

outputs 2

join

(d='', attr=None)

Convert a list value into a string which is the concatenation of the strings in the sequence. Set d to add a separator string to join the items. Set attr to join attributes within the value object.

{% set test = ['a', 'b', 'c'] %}
{{ test | join('|') }}

outputs 'a|b|c'

{% set test = [{'num': 1}, {'num': 2}, {'num': 3}] %}
{{ test | join('|', 'num') }}

outputs '1|2|3'

last

Return the last item of a sequence.

{% set test = [1, 2, 3, 4] %}
{{ test | last }}
outputs 4

{% set test = [{'count': 1}, {'count': 2}, {'count': 3}] %}
{% set last = test | last %}
sets last to {'count': 3}

{{ last.count }}
outputs 3

length

Return the number of items of a sequence or mapping.

{% set test = [{"title": 'The Big Lebowski'}, {'title': 'Fargo'}] %}
{{ test | length }}

outputs 2

list

Convert the value into a list. If value is an object, the keys will be returned as strings in an unordered list. It value is a string the returned list will be a list of characters.

{% set test = {'title': 'The Big Lebowski', 'director': 'Ethan Coen'} %}
{% set newList = test | list %}

sets newList to ['director', 'title']

{% set test = 'Ethan Coen' %}
{% set newList = test | list %}

sets newList to ['E', 't', 'h', 'a', 'n', ' ', 'C', 'o', 'e', 'n']

lower

Convert all characters in a string value to lowercase. If value is an object, the keys and values will be lowercased. If the value is a list, all values will be lowercased.

{% set test = 'rAndom CApitaLs are noW LoWeR caseD' %}
{{ test | lower }}

outputs: 'random capitals are now lower cased'

{% set activities = ["hiking", "SWImmInG", "cycLing"] %}
{% set activities = activities | lower %}

lower cases activities to ['hiking', 'swimming', 'cycling']

lpdatetime

(string)

Convert human readable string to a datetime object. Returns null in case of bad format.

{{ lpdatetime('2021-01-05') }}

outputs: 2021-01-05 00:00:00

{{ lpdatetime('2021-01-05 13:15') }}

outputs: 2021-01-05 13:15:00

{{ lpdatetime('2021-01-05') | datetimeformat('%Y/%m/%d') }}

outputs: 2021/01/05

lpusertimezone

(datetime)

Returns the same moment of a datetime object defined in the users timezone (if available).

# Current time: 2021-02-18 09:15:00 UTC
# Users Timezone: UTC+2

{{ now() | lpusertimezone }}

outputs: 2021-02-18 11:15:00


# Users Timezone: UTC+3

{% set date = '2021-01-05 13:15' %}
{{ date | lpdatetime | lpusertimezone }}

outputs: 2021-02-18 16:15:00

lpversion

(string)

Parse a string to SemVer specification. Returns null if it fails to do so. You can compare built-in variable appVersion with a string parsed as SemVer

{% set ver = '5.0.9' | lpversion %}
{% if ver > lpversion('5.2') %} 
Version is higher than 5.2
{% else %} 
Version is lower than 5.2
{% endif %}

outputs: "Version is lower than 5.2"


# Current version of the app is 5.3.1

{% if appVersion > lpversion('5.3.0') %} 
Version is higher than 5.3.0
{% else %} 
Version is lower than 5.3.0
{% endif %}

outputs: "Version is higher than 5.3.0"

map

Applies a filter on a sequence of objects, or looks up an attribute. To look up an attribute, you must use attribute=. You may need to apply another filter in a chain to get the results of the map.

{% set fullName = ['Joe', 'Brett', 'Ross'] %}
{{ fullName | map('capitalize') | join(' ') }}

{# Comment: Or if you need access to an attribute #}

{% set test = [
  {'title': 'The Big Lebowski', 'director': 'Ethan Coen'},
  {'title': 'The Pink Panther', 'director': 'Blake Edwards'}
] %}

{% set newList = test | map(attribute='director') | list %}

maps all 'director' items, then applies the list filter to get results.
sets newList to ['Ethan Coen', 'Blake Edwards']

{{ test | map(attribute='director') | join(', ') }}

outputs: 'Ethan Coen, Blake Edwards'

md5

Calculates the md5 hash of the given object.

{{ 'unhashed string' | md5 }}

outputs the md5 hash of the string

minus_time

(diff, 'unit')

Subtracts a specified amount of time to a datetime object.
diff - Integer. The amount to subtract from the datetime. Required.
'unit' - String. Which temporal unit to use eg 'days',' 'hours', 'minutes' etc. Required.

Today is 2020-04-09T00:00Z

{{ today()|minus_time(5,'days') }}

outputs: 2020-04-04 00:00:00

mstotime

(milliseconds)

Parses timestamp in milliseconds and returns the moment in UTC as a datetime object.

{{ 1613690568000 | mstotime }}

outputs: 2021-02-18 23:22:48

multiply

(multiplier)

Multiplies the current object with the given multiplier.

{{ 5 | multiply(2) }}

outputs: 10

numberformat

(formatSpec)

Formats a number. In formatSpec, use 0 to represent a required digit, # an optional digit, dot (.) to represent a decimal separator, and (,) to represent a grouping separator. For more information, see Oracle's docs.

parsejson

'(JSON string}'

Parses a given JSON string value as a JSON object Most commonly used to parse a user attribute as a list.

User attribute ExampleList = ["ItemA","ItemB","ItemC"]

{{ userAttribute['ExampleList] | parsejson | first }}

outputs 'ItemA'

plus_time

(diff, 'unit')

Adds a specified amount of time to a datetime object.
diff - Integer. The amount to add from the datetime. Required.
'unit' - String. Which temporal unit to use eg 'days',' 'hours', 'minutes' etc. Required.

Today is 2020-04-09T00:00Z

{{ today()|plus_time(5,'days') }}

outputs: 2020-04-14 00:00:00

pprint

Pretty print a variable. Useful for debugging.

{% set userAttributes = { 'activities': ["hiking", "swimming", "cycling"], 'name': 'Hubert', 'email': '[email protected]' }
%}
{{ userAttributes | pprint }}

outputs:
{'activities': ['hiking', 'swimming', 'cycling'],
 'email': '[email protected]',
 'name': 'Hubert'}

random

Return a random item from a list/sequence.

{% set test = ["hiking", "swimming", "cycling"] %}
{{ test | random }}

reject

Filters a sequence of objects by applying a test to the object and rejecting the ones with the test succeeding. See Expression Tests. Any additional arguments will be passed to the Test function. If no test is specified, each object will be evaluated as a boolean.

Since this returns a generator object, you should use the list filter to cast it back to a list.

{% set test = [1, 2, 3, 4, 5, 6, 7, 8] %}
{% set newList = test | reject("equalto", 3) | list %}

sets newList to [1, 2, 4, 5, 6, 7, 8]

{% set newList = test | reject("even") | list %}
 
sets newList to [1, 3, 5, 7]

{% set test = [1, 2, 3, "unwantedString", 4, 5] %}
{% set newList = test | reject("string") | list %}

sets newList to [1, 2, 3, 4, 5]

{% set test = [False, 2, True, "string", 4, 5] %}
{% set newList = test | reject | list %}

sets newList to [False]

rejectattr

(attribute, test)

Filters a sequence of objects by applying a test to an attribute of an object, and rejecting the ones with the test succeeding. If no test is specified, the attribute’s value will be evaluated as a boolean. See Expression Tests.

Any additional arguments will be passed directly to the Test function.

Since this returns a generator object, you should use the list filter to cast it back to a list.

{% set test = [
    {'name': 'Bill', 'age': 30},
    {'name': 'Jane', 'age': 31}
] %}
{% set newList = test | rejectattr("age", "odd") | list %}

sets newList to [{'age': 30, 'name': 'Bill'}]

{% set newList = test | rejectattr("age", "equalto", 30) | list %}

sets newList to [{'age': 31, 'name': 'Jane'}]

replace

(old, new, count=None)

Return a copy of the value with all occurrences of a substring replaced with a new one. The first argument, old, is the substring that should be replaced, the second (new) is the replacement string. Use the third argument count to limit the number of occurrences to be replaced.

{% set originalString = 'numnum'%}
{{ originalString | replace("num", "new") }}

outputs 'newnew'

{% set originalString = 'numnum'%}
{{ originalString | replace("num", "new", 1) }}

outputs 'newnum'

reverse

Reverse the object or return an iterator the iterates over it the other way round.

{% set originalList = [0, 1, 2, 3, 4] %}
{% set reversedList = originalList | reverse | list %}

sets reversedList to [4, 3, 2, 1, 0]

round

`(precision, precision=0, method='common')

Round the number to a given precision (defaults to 0). Set the method of rounding to either common (rounds up or down), ceil (always rounds up), or floor (always rounds down).

{{ 42.55 | round }}

outputs 43.0

{{ 43.553423 | round(3, 'ceil') }}

outputs: 43.554

Note that even if rounded to 0 precision, a float is returned. If you need a real integer, chain it with the int filter:

{{ 42.55 | round | int }}

outputs 43

safe

Mark the value as safe, which means that in an environment with automatic escaping enabled this variable will not be escaped.

sectotime

(seconds)

Parses timestamp in seconds and returns the moment in UTC as a datetime object.

{{ 1613690568 | sectotime }}

outputs: 2021-02-18 23:22:48

select

(test)

Filters a sequence of objects by applying a test to the object and only selecting the ones with the test succeeding. Any additional arguments will be passed to the test function. See Expression Tests for a complete list.

{% set numbers = [0,1,2,3,4,5,6,7,8] %}

{{ numbers | select("odd") | list}}

outputs: [1, 3, 5, 7]

{{ numbers | select("divisibleby", 3) | list}}

outputs: [0, 3, 6]

{{ numbers | select("lessthan", 4) | list }}

outputs: [0, 1, 2, 3]

selectattr

(attr, exp_test)

Filters a sequence of objects by applying a test to an attribute of an object and only selecting the ones with the test succeeding. Any additional arguments will be passed to the test function. See Expression Tests for a complete list.

{% set users = [
    {'name': 'Bill', 'age': 30},
    {'name': 'Jen', 'age': 39},
    {'name': 'David', 'age': 23},
] %}

{% set olderUsers = users | selectattr('age', 'greaterthan', 25) | list %}

sets olderUsers to: 
[{'age': 30, 'name': 'Bill'}, {'age': 39, 'name': 'Jen'}]

{% set youngerUsers = users | selectattr('age', 'lessthan', 25) | list %}

sets youngerUsers to:
[{'age': 23, 'name': 'David'}]

shuffle

Randomly shuffle a given list, returning a new list with all of the items of the original list in a random order.

slice

(slices, fill_with=None)

Slice an iterator and return a list of lists containing those items, where slices determines the number of lists created. Use fill_with to fill in any missing values.

{% set basicList = [0,1,2,3,4,5,6,7,8] %}
{% set newList = basicList | slice(2, 'filler_word') | list %}

sets newList to: 
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 'filler_word']]

{% set newList = basicList | slice(3, 'filler_word') | list %}

sets newList to:
[[0, 1, 2, 'filler_word'], [3, 4, 5, 'filler_word'], [6, 7, 8, 'filler_word']]

sort

(reverse=False, case_sensitive=False, attribute=None)

Sort an iterable. By default, it sorts items in ascending order, unless reverse=True, and ignores case, unless case_sensitive=True. Optionally pass an attribute to sort a list of objects by a particular attribute.

{% set nameList = [
    {'name': 'Bob', 'age': 30},
    {'name': 'Jane', 'age': 31},
    {'name': 'Zach', 'age': 45}
] %}
{% set newList = nameList | sort(True, attribute='name') %}

sets newList to:
[
    {'age': 45, 'name': 'Zach'}, 
    {'age': 31, 'name': 'Jane'}, 
    {'age': 30, 'name': 'Bob'}
]

{% for item in nameList | sort(True, attribute='name') %}
    {{item.name}}
{% endfor %}

outputs:
Zach
Jane
Bob

split

(separator, limit)

Splits the input string into a list on the given separator.

{% set splitFullName = userAttribute['fullName'] | split(' ', 2) %} 
First Name = {{splitFullName[0]}}
Last Name = {{splitFullName[1]}}

string

Returns string value of object.

{%- set unreadCount = 9 -%}
{{ 'You have ' + unreadCount | string + ' unread messages.'}}

outputs:
You have 9 unread messages.

striptags

Strip SGML/XML tags and replace adjacent whitespace by one space.

strtotime

("format")

Converts a datetime string and datetime format to a datetime object. Date time operations can be performed on the returned object.
format - String. Format of the datetime string. Example "yyyy-MM-dd'T'HH:mm:ssXXX"

{{ '2020-08-15T00:00:00Z'|strtotime("yyyy-MM-dd'T'HH:mm:ssXXX" )}}

outputs: 2020-08-15 00:00:00

sum

(attribute=None, start=0)

Returns the sum of a sequence of numbers plus the value of parameter ‘start’ (which defaults to 0). When the sequence is empty it returns start. Include an attribute to sum values of that attribute.

{% set nums = [1,2,9] %}
{{ nums | sum(start=2) }}

outputs: 14

{% set items = [
    {'name': 't-shirt', 'price': 19.99},
    {'name': 'jeans', 'price': 109.99},
    {'name': 'sweater', 'price': 45.99}
] %}
{{ items | sum(attribute='price') }}

outputs: 175.97

title

Return a titlecased version of the value (i.e. words will start with uppercase letters, all remaining characters are lowercase).

{% set lower = 'this must be the place' %}
{{ lower | title }}

outputs: This Must Be The Place

trim

Strip leading and trailing whitespace.

truncate

(string, length=255, killwords=False, end='...')

Return a truncated copy of the string of length length (defaults to 255), and overwrites the last characters with end. Use killwords to either cut the text at the exact length (True), or discard the last word (False). If you want a different ellipsis sign than "..." you can specify it using the third parameter.

{%- set long = 'this is a really long sentence   ' %}
{{ truncate(long, 19, killwords=True) }}

outputs: this is a really...

{{ truncate(long, 19, killwords=False) }}

outputs: this is a...

truncatehtml

(length=255, end="...", breakword=False)

Truncates a given string, respecting html markup (i.e. will properly close all nested tags).

unique

(case_sensitive=False, attribute=None)

Filter duplicated strings from a sequence of strings

{{ ['foo', 'bar', 'foo', 'other'] | unique | join(', ') }}

Outputs: foo, bar, other

unixtimestamp

Gets the UNIX timestamp value (in milliseconds) of a date object

Today is 2020-04-09T00:00Z

{{ today()|unixtimestamp }}

outputs: 1586390400000

upper

Convert a value to uppercase.

{{ 'this must be the place' | upper }}

outputs: THIS MUST BE THE PLACE

urlencode

Escape strings for use in URLs (uses UTF-8 encoding). It accepts both dictionaries and regular strings as well as pairwise iterables.

The following rules are used for encoding:

  • The alphanumeric characters "a" through "z", "A" through "Z" and "0" through "9" remain the same.
  • The special characters ".", "-", "*", and "_" remain the same.
  • The space character " " is converted into a plus sign "+".
  • All other characters are unsafe and are first converted into one or more bytes using UTF-8 encoding. Then each byte is # represented by the 3-character string "%xy", where xy is the two-digit hexadecimal representation of the byte.
Note:

If spaces are required to be encoded as '%20' instead of '+', add a replace filter chained after urlencode. See example below.

{% set params = {'user': 'jqeveryman', 'attr': 'space test'} %}
{{ 'https://www.example.com/api?' + params | urlencode }}

outputs: https://www.example.com/api?user=jqeveryman&attr=space+test

{% set attr = 'space test' %}
{{ 'https://www.example.com/api?user=jqeveryman&attr=' + attr | urlencode }}

outputs: https://www.example.com/api?user=jqeveryman&attr=space+test

{% set replace_encoded_attr = 'space test' %}
{{ 'https://www.example.com/api?user=jqeveryman&attr=' + replace_encoded_attr | urlencode | replace('+', '%20') }}

outputs: https://www.example.com/api?user=jqeveryman&attr=space%20test

urlize

(trim_url_limit=None, nofollow=False, target=None)

Converts URLs in plain text into clickable links, with a max length of trim_url_limit. Optionally, set nofollow to True to add nofollow to the generated link tag, and set the target to add a target attribute to the generated link tag.

{% set link = 'http://www.google.com' %}
{{ link | urlize(target="_blank") }}

outputs: <a href="http://www.google.com" rel="noopener" target="_blank">http://www.google.com</a>

wordcount

Counts the words in the given string.

wordwrap

(width=79, break_long_words=True)

Return a copy of the string passed to the filter wrapped after 79 characters. Set break_long_words to False to not split words that are longer than width.

{% set text = 'this is the start of a really long paragraph about many different things.' %}
{{ text | wordwrap(20) }}

outputs:
this is the start of
a really long
paragraph about many
different things.

xmlattr

(autospace=True)

Create an HTML/XML attribute string based on the items in a dict. Set autospace to False to prevent the filter from automatically prepending a space in front of the item.

{% set attrs = {
    'class': 'col-9 active',
    'id': 'column1'
} %}
<div{{ attrs | xmlattr }}></div>

outputs: 
<div class="col-9 active" id="column1"></div>