Legacy template helpers Last updated: 26. Oct 2026
Before HashJS supported standard JavaScript, Docly's template language had a set of global helper functions. They still work so that existing templates keep running, but they have pitfalls, and new code should use standard JavaScript. In template mode (.hash pages and schema templates) they are global functions; in API mode (#/API files and services) they exist only with the docly. prefix, for example docly.cint(x).
Numbers
Helper | What it does | Pitfalls and what to use instead |
|---|---|---|
add(a, b, …), sub(…), mul(…), div(…) | Adds, subtracts, multiplies or divides the arguments from left to right. | Text that is not a number counts as 0, so a mistake gives a wrong number instead of an error. div() by 0 gives Infinity. Use + - * /. |
mod(a, b) | Remainder of a divided by b. | Use %. |
sum(array[, field]), avg(array, field) | Sum or average of the items, or of a field on each item. | Values that are not numbers count as 0. avg() of an empty array gives NaN. Use reduce(). |
round(x), floor(x), ceiling(x) | Same as Math.round, Math.floor and Math.ceil. | round() takes no decimals argument: round(1.234, 2) gives 1. Use Math.round(x * 100) / 100, or x.toFixed(2) for display. |
cint(x) | Converts to a whole number. | Rounds half to even (2.5 gives 2, 3.5 gives 4), unlike Math.round. Anything that is not a number, or is too large, gives 0. Use parseInt() or Math.round(). |
cdbl(x) | Converts to a number. | Accepts a comma as decimal separator; text that is not a number gives null. parseFloat() and Number() follow standard JavaScript and stop at a comma. |
Text and dates
Helper | What it does | Pitfalls and what to use instead |
|---|---|---|
cstr(a, …) | Converts the arguments to text and joins them. | Use String(x) or a template literal. |
cdate(text[, format]) | Reads a date from text. Without format: yyyy-MM-dd, or yyyy-MM-ddTHH:mm:ss when the text contains a T. | Anything else — including a time zone suffix (Z, +02:00) or a time without seconds — gives null. Use new Date(text) or Date.parse(text). |
getDate() | The current date and time. | Use new Date(). |
trim(text[, chars]) | Trims white space, or the given characters, from both ends. | Use text.trim(). |
substring(…) | Not implemented: the global helper always returns null. | Use text.substring(start, end) or text.slice(). |
replace(text, find, replacement) | Replaces ALL occurrences. | The method text.replace(find, r) replaces only the first. Use text.replaceAll(). |
split(text[, separator]) | Without separator: splits by line breaks and drops empty lines. With separator: like text.split(separator). | Use text.split(). |
lcase(…), ucase(…) | Lower or upper case of the arguments, joined. | Use toLowerCase() / toUpperCase(). |
join(a, b, …) and join(separator, lastSeparator, array) | Joins the arguments as text. With three arguments where the last is an array, joins the array with separator but uses lastSeparator before the last item: join(", ", " and ", ["a", "b", "c"]) gives "a, b and c". | Not the same as array.join(separator). |
padLeft(text, fill, length), padRight(…) | Pads the text to the given length. | Use text.padStart(length, fill) / padEnd() — note the different argument order. |
Arrays
Helper | What it does | Pitfalls and what to use instead |
|---|---|---|
first(array[, condition]), last(array), getFirst(array), getLast(array) | The first or last item; first() can take a condition. | Use array[0], array.at(-1) or array.find(). |
take(array, n), skip(array, n) | The first n items / all but the first n items. | Use slice(0, n) / slice(n). |
getIndex(array, i) | The item at index i. | Use array[i]. |
getBy(array, field, value) | The first item whose field equals value. | Both field and value are text that is evaluated as an expression, so a field name must be quoted inside the text ("'id'"), and the comparison uses .NET equality. Use array.find(x => x.id == 42). |
where(array, condition), any(array, condition) | The items that match / whether any item matches a condition. | The condition is text in the old bracket-condition syntax, evaluated with each item as the current object. Use filter() / some(). |
select(array, field) | Collects the values of field from all items and flattens them into one array. | Field values that are not arrays are skipped — and a text value is split into single characters. Use map(): items.map(x => x.field). |
distinct(array) | Removes duplicates. | Objects are compared by reference. Use [...new Set(array)]. |
union(a, b, …) | Joins arrays (or Sets) into one array. | Throws if an argument is not an array. Use concat() or spread. |
insertAt(array, index, item) | Returns a new array with the item inserted. | Use splice(). |
push(array, item, …), pop(array) | Adds items to the end / removes the last item. | push() returns the array, not the length. Use array.push() / array.pop(). |
and(a, b, …), or(a, b, …) | true if all / any of the arguments are truthy. | Every argument is evaluated first — there is no short-circuit. Use && and ||. |
setProp(name, property, value) | Sets a property on the object stored in the variable name. | The object is copied through JSON, so the variable gets a new object. Use obj.property = value. |
Always available
These helpers exist without the docly. prefix in both modes:
Helper | What it does | Notes |
|---|---|---|
nullc(a, b, …) | Returns the first argument that is not null, empty or only white space; otherwise "". | Unlike ??, it also skips "" and " ". |
setvar(name, value), getvar(name), get(name) | Sets or reads a variable by name. | Use normal variables in new code. |
sort(array, field[, convert]), sortDesc(…) | Sorts items by a field. convert is the name of a function, such as "parseInt", applied to each value first. | Numbers sort numerically and dates chronologically; items without the field come first (last with sortDesc). Items with equal values keep their order. |