Rat docs

Strings

The string builtins cover the basics every web app reaches for: case folding, whitespace trimming, splitting and joining, substring search and replace, prefix/suffix checks, padding for column alignment, and a positional format for templated output. Every call works identically on the server (during > server evaluation) and in the browser (inside handlers) — same name, same result.

upper / lower

Case folding, ASCII + Unicode aware

upper(s) and lower(s) return a new string with the case folded. They handle Unicode — accented characters and non-Latin scripts round-trip correctly.

<p> [upper('hello')]
<p> [lower('WORLD')]
Result

HELLO

world

trim — strip leading and trailing whitespace

Inner spaces are preserved

trim(s) removes whitespace (spaces, tabs, newlines) from both ends of the string. Useful for cleaning up form input before validation. Inner whitespace is left alone — use regex.replace if you need to collapse runs.

<p> ([trim('  hi  ')])
Result

(hi)

split / join — array bridge

Two halves of the same conversion

split(s, sep) cuts a string on a delimiter into an array. join(arr, sep) is the inverse — turns an array of strings into a delimited string. Together they let you reshape "list-as-string" data without touching the loop.

<p> [split('a,b,c', ',')]
<p> [join(items, ' / ')]
Result

split: [a, b, c]

join: apples / pears / figs

replace — all occurrences

No regex, no special chars

replace(s, from, to) swaps every occurrence of a literal substring. There are no escape rules — every character is matched literally. For pattern-based replacement, use regex.replace from the regex namespace.

<p> [replace('foo bar foo', 'foo', 'baz')]
Result

baz bar baz

starts_with / ends_with / contains

Three substring predicates, return booleans

Each takes the haystack first and the needle second, returning true or false. contains is overloaded — it also works on arrays (element membership) and objects (key membership), which is convenient when the data shape changes between two call sites.

<p> [starts_with('hello world', 'hello')]
<p> [ends_with('hello world', 'world')]
<p> [contains('hello world', 'lo wo')]
<p> [contains(items, 'pears')]
Result

starts: true

ends: true

contains string: true

contains array: true

pad_left / pad_right

Fixed-width alignment for tables and IDs

pad_left(s, width, char) prepends the pad character until the result is the requested width; pad_right appends instead. If the input is already at or over the width, it's returned unchanged. Common use: zero-padding numeric IDs for sortable filenames.

<p> ([pad_left('7', 3, '0')])
<p> ([pad_right('7', 3, '.')])
Result

pad_left: (007)

pad_right: (7..)

repeat — concat N times

Quick separators, ASCII art, retry indicators

repeat(s, n) joins n copies of s into one string. Useful for rules in plain-text output, leader dots, or progress bars.

<p> [repeat('ab', 3)]
<p> [repeat('-', 20)]
Result

ababab

--------------------

format — positional placeholders

{} consumes args in order; no named slots

format(template, args...) substitutes each {} with the next argument. There are no named or indexed slots — order is the contract. The format spec mirrors the simplest Python f-string subset on purpose; reach for prose concatenation when you need anything richer.

<p> [format('hi {}', 'world')]
<p> [format('{} + {} = {}', 1, 2, 3)]
Result

hi world

1 + 2 = 3

Next: Math — floor, ceil, round, clamp, lerp, min/max, abs.