Pen-scripts functions

Operators

:sum

Return the sum of a list of values:

{
	":sum": [3, 5, 10]
}

Is undefined if an element of the list is a string or an object.

:product

Returns the product of a list of values:

{
	":product": [12, 5]
}

:max

Returns the max of a list of values:

{
	":max": [12, 5]
}
{
    ":max": [
        { ":date": "2022-12-01" },
        { ":date": "2022-01-01" }
    ]
}

Also works with date formats (check second tab).

:min

Returns the min of a list of values:

{
	":min": [12, 5]
}
{
    ":min": [
        { ":date": "2022-12-01" },
        { ":date": "2022-01-01" }
    ]
}

Also works with date formats (check second tab).

:increasing

Returns true if the second value is higher than the first value provided in the list:

{
	":increasing": [12, 5]
}

Logic

:if :then :else

Evaluate expression in :if. Return :then if expression returns a trurthy value (eg: a string not empty is a truthy value), return :else otherwise.

{
  ":if": {},
  ":then": {},
  ":else": {}
}

:case :when

Evaluate a value and return the block associated with the value (in most language it corresponds to a switch):

{
    ":case": "{ data.my_key }",
    ":when": [
        [
            "val1",
            {}
        ],
        [
            "val2",
            {}
        ],
        [
            "val3",
            {}
        ]
    ]
}

:defined

Returns true if the evaluated expression is defined (neither null nor undefined).

Example:

{
  ":defined": "{data.key}"
}

:cmp

Compare a value with an other value using a function.

The list of possible functions:

  • :eq compares if the two elements are equal
  • :gt compares if the first element is greater than the second one
  • :ge compares if the first element is greater or equal to the second one
  • :lt compares if the first element is lower than the second one
  • :le compares if the first element is lower or equal to the second one
{
  ":cmp": "{data.my_var}",
  ":eq": 2 // could be "my_value"
}

:in

Evaluate if a value is present in a list:

{
  ":in": ["val1", ["val1", "val2"]]
}

:includes

Evaluate if a list contains a value:

{
  ":includes": [["val1", "val2"], "val1"]
}

:intersects

Evaluate of some elements from a list can be found in some elements from an other list:

{
  ":intersects": [["val1", "val2"], ["val1", "val3"]]
}

:not

Give the reverse boolean value of an expression:

{
  ":not": true
}

:true

Evaluate if an expression is true.

{
  ":true": "{data.my_var}"
}

:false

Evaluate if an expression is false.

{
  ":false": "{data.my_var}"
}

:every

Evaluate if all the expressions in the list return a truthy value

{
  ":every": [{":defined": "{data.my_var}"}, "{data.my_other_var}"]
}

:some

Evaluate if at least one of the expressions in the list return a truthy value

{
  ":some": [{":defined": "{data.my_var}"}, "{data.my_other_var}"]
}

:coalesce

Returns the first undefined value of an list:

{
	":coalesce": [null, "{data.some_undefined_value}", "default value"]
}

List & loops

:range

Return a list of integer from index_start to index_end:

{
  ":range": [index_start, index_end]
}

{":range": [4, 10]} will return a value of [4, 5, 6, 7, 8, 9].

:array :fill

Create an array with a specified length and optionally fill it using an expression.

{
  ":array": 5,
  ":fill": {
    "label": "Contact person {@position}",
    "elements": []
  }
}

The following variables are accessible in the :fill context:

  • @first: boolean, true if first item
  • @index: current index, starting counting at 0
  • @position: current position. Equals to index + 1
  • @last: boolean, true if last item

:map :to

Loop in a list and return an array evaluated for every element found.

{
  ":map": ["foo", "bar"],
  ":to": []
}

It can also be:

{
  "foo": {
    ":map": [
      {"key1": "foo", "key2": "bar"},
      {"key1": "ding", "key2": "dong"}
    ],
    ":to": [
      "{@item.key1}"
    ]
}

The following variables are accessible in the :to context:

  • @item: the content of the current item
  • @first: boolean, true if first item
  • @index: current index, starting counting at 0
  • @position: current position. Equals to index + 1
  • @last: boolean, true if last item

Objects

:assign

Based on the list of objects provided, overwrite the keys of the current object with the later.

Example:

{
  ":assign": [
    {
      "key1": "foo",
      "key2": "bar"
    },
    {
      "key2": "foo2"
    }
  ]
}

Result:

{
  "key1": "foo",
  "key2": "foo2"
}

:object-entries

Transform an object into a list with the input evaluated in ::as. Optional argument ::order-bywith value keyor value.

Example:

{
	"variables": [
    {
      "test_object": {
        "gender": "female",
        "given_name": "Olivia",
        "family_name": "De Smet"
      }
    },
    {
      "test2": {
        ":object-entries": "{user}",
        ":as": {
          "key": "{@value}",
          "value": "{@key}"
        }
      },
      "test": {
        ":object-entries": "{user}",
        ":as": "{@value}"
      }
    }
  ]
}

Will return:

{
  "test2": [
    {
      "key": "De Smet",
      "value": "family_name"
    },
    {
      "key": "female",
      "value": "gender"
    },
    {
      "key": "Olivia",
      "value": "given_name"
    }
  ],
  "test": [
    "De Smet",
    "female",
    "Olivia"
  ]
}

What’s Next

in the next chapter we'll focus on the signature element.