Methods
A method is written after a value: answers.name.upper(). A method on a missing value gives null, not an error.
A method must fit the value it is called on. A text value has the text methods and a date has the date methods, so today().subDays(90) cannot work: today() gives text. Publishing refuses an expression with a method that cannot apply to its value, and says why. Write mash.date.today().subDays(90) instead.
Every method here is pure. It reads and returns a value, and never changes the form.
List methods
Section titled “List methods”A list is a table’s rows, a Choice that allows several options, or a list you write. These methods work on a list directly, or on mash.collect(list), which gives [] when the answer is missing.
| Method | Gives |
|---|---|
sum('key'), avg('key'), average('key'), min('key'), max('key') | The total, average, lowest or highest of a column. |
count() | The number of rows. |
pluck('key') | A list of one column. |
first(), last() | The first or last row. |
contains('key', value) | True when a row has that value. |
where('key', value) | The rows where the column equals the value. |
unique() | The list without repeats. |
implode('key', separator) | One column joined as text. |
isEmpty(), isNotEmpty() | Whether the list has rows. |
{"answers": {"rows": [{"type": "car", "amount": 10}, {"type": "bus", "amount": 20}, {"type": "car", "amount": 30}]}}mash.collect(answers.rows).sum('amount')60answers.rows.count()3mash.collect(answers.rows).where('type', 'car').count()2mash.collect(answers.rows).pluck('amount')[10,20,30]sum(mash.collect(answers.rows).pluck('amount'))60mash.collect(answers.rows).contains('type', 'bus')truemash.collect(answers.missing).sum('amount')0A budget check on a table:
{"answers": {"rows": [{"amount": 10}, {"amount": 20}], "budget": 50}}mash.collect(answers.rows).sum('amount') <= answers.budgettrueText methods
Section titled “Text methods”Call these on a text answer, or on mash.str(value), which turns any value into text.
| Method | Gives |
|---|---|
upper(), lower(), trim() | The text in capitals, in lower case, without spaces at the ends. |
title() | The first letter capitalised. title(true) capitalises every word. |
length() | The number of characters. |
slice(start, length) | Part of the text. A negative start counts from the end. |
replace(from, to) | The text with every from replaced. |
startsWith(x), endsWith(x), containsAny(x) | True or false. |
before(x) | The text before the first x, or all of it if x is not there. |
after(x) | The text after the first x, or "" if x is not there. |
{"answers": {"name": " ada ", "v": "Hazardous|Asbestos|x"}}mash.str(answers.name).trim().upper()"ADA"mash.str('hello world').title(true)"Hello World"mash.str('hello world').slice(0, 5)"hello"mash.str('a-b-c').replace('-', '_')"a_b_c"answers.v.before('|')"Hazardous"answers.v.after('|')"Asbestos|x"before and after suit a Lookup whose value packs two things, such as Hazardous|Asbestos.
Number methods
Section titled “Number methods”These are on mash.math.
| Method | Gives |
|---|---|
mash.math.round(x, places) | x rounded. Halves round away from 0. |
mash.math.floor(x), mash.math.ceil(x) | Rounded down or up. |
mash.math.abs(x), mash.math.sqrt(x), mash.math.pow(x, y) | Absolute value, square root, power. |
mash.math.toInt(x) | The whole part, towards 0. |
mash.math.isNumeric(x), mash.math.isNan(x) | True or false. |
mash.math.round(13.456, 2)13.46mash.math.round(-2.5)-3mash.math.toInt(-7.9)-7mash.math.isNumeric('abc')falseRound a table total to pennies:
{"answers": {"r": [{"amount": 10.1}, {"amount": 20.246}]}}mash.math.round(mash.collect(answers.r).sum('amount'), 2)30.35Date methods
Section titled “Date methods”mash.date.parse(value) turns a date answer or text such as 2026-07-10 into a date. A blank or unreadable value gives null. mash.date.today() and mash.date.now() give the clock of the form. A date written back out as text is YYYY-MM-DD HH:MM:SS.
| Method | Gives |
|---|---|
diffInDays(other), diffInWeeks, diffInMonths, diffInYears, diffInHours, diffInMinutes | The signed difference from this date to other. |
diffInWeekdays(other), diffInWeekendDays(other) | Working days or weekend days from this date, counting it, up to but not counting other. |
add(n, unit), sub(n, unit) | The date moved by n days, weeks, months, years, hours or minutes. |
addDays(n), subDays(n) | The date moved by n days. |
toDateString(), toDateTimeString(), format(pattern) | The date as text. |
year, month, day, hour, minute, dayOfWeek, dayOfWeekIso | One part of the date. dayOfWeek counts Sunday as 0 and dayOfWeekIso counts it as 7. |
{"_now": "2026-07-10T12:34:56.000Z", "answers": {"a": "2026-07-01", "b": "2026-07-10", "start": "2026-07-13", "end": "2026-07-17"}}mash.date.parse(answers.a).diffInDays(mash.date.parse(answers.b))9mash.date.parse(answers.b).diffInDays(mash.date.parse(answers.a))-9mash.date.parse('2026-07-10').addDays(5).toDateString()"2026-07-15"mash.date.parse('2026-07-10').add(2, 'weeks').toDateString()"2026-07-24"mash.date.parse('2026-07-10').format('dd/MM/yyyy')"10/07/2026"mash.date.today().toDateString()"2026-07-10"mash.date.parse('2026-07-12').dayOfWeekIso7Counting days of leave, both ends included, is the difference plus one. A blank end date still gives an answer:
mash.date.parse(answers.start).diffInDays(mash.date.parse(answers.end)) + 15Working days, with both ends included:
mash.date.parse(answers.start).diffInWeekdays(mash.date.parse(answers.end).addDays(1))5Adding a month to the 31st goes into the next month, as it does in a calendar library:
mash.date.parse('2026-01-31').add(1, 'month').toDateString()"2026-03-03"Dates compare with <, > and ==:
mash.date.parse(answers.a) < mash.date.parse(answers.b)trueA date that cannot be read gives null, and so do the methods on it:
mash.date.parse('nonsense')null