Expression
Every field is a JavaScript expression. The Math page covers the everyday 90%; this page is the complete reference.
(width - gap * (n - 1)) / n // arithmetic
open ? 0 : depth // a choice
sizes.map(s => s + clearance) // a list
Math.max(a, b, c) // a library callOperators
| Group | Operators |
|---|---|
| Arithmetic | + - * / % ** |
| Compare | < <= > >= == === != !== |
| Logical | && || ! |
| Choice | cond ? a : b |
Standard library
Available globals: Math, Number, String, Array, Object, Boolean, parseInt, parseFloat, isNaN.
Math (MDN →)
| Method / Constant | Description | Example → result |
|---|---|---|
Math.PI | π ≈ 3.14159 | Math.PI * r * r |
Math.E | e ≈ 2.71828 | Math.exp(1) |
Math.abs(x) | Absolute value | Math.abs(-5) → 5 |
Math.ceil(x) | Round up | Math.ceil(4.1) → 5 |
Math.floor(x) | Round down | Math.floor(4.9) → 4 |
Math.round(x) | Round to nearest | Math.round(4.5) → 5 |
Math.trunc(x) | Drop decimal part | Math.trunc(-4.9) → -4 |
Math.sign(x) | -1 / 0 / +1 | Math.sign(-3) → -1 |
Math.min(a, b, …) | Smallest value | Math.min(3, 1, 2) → 1 |
Math.max(a, b, …) | Largest value | Math.max(3, 1, 2) → 3 |
Math.sqrt(x) | Square root | Math.sqrt(9) → 3 |
Math.cbrt(x) | Cube root | Math.cbrt(27) → 3 |
Math.pow(x, y) | x to the power y (same as x**y) | Math.pow(2, 10) → 1024 |
Math.hypot(a, b, …) | √(a²+b²+…) — diagonal | Math.hypot(3, 4) → 5 |
Math.sin(rad) | Sine (input in radians) | Math.sin(Math.PI/2) → 1 |
Math.cos(rad) | Cosine (radians) | Math.cos(0) → 1 |
Math.tan(rad) | Tangent (radians) | Math.tan(Math.PI/4) → 1 |
Math.asin(x) | Arcsine → radians | Math.asin(1) → 1.5708 |
Math.acos(x) | Arccosine → radians | Math.acos(0) → 1.5708 |
Math.atan(x) | Arctangent → radians | Math.atan(1) → 0.7854 |
Math.atan2(y, x) | Angle of vector (y,x) → radians | Math.atan2(1,1) → 0.7854 |
Math.log(x) | Natural log ln(x) | Math.log(Math.E) → 1 |
Math.log2(x) | Log base 2 | Math.log2(8) → 3 |
Math.log10(x) | Log base 10 | Math.log10(1000) → 3 |
Math.exp(x) | eˣ | Math.exp(1) → 2.71828 |
Number (MDN →)
| Method / Constant | Description | Example → result |
|---|---|---|
Number.isFinite(x) | true if finite number | Number.isFinite(1/0) → false |
Number.isInteger(x) | true if whole number | Number.isInteger(3.0) → true |
Number.isNaN(x) | true if exactly NaN (no coercion) | Number.isNaN(NaN) → true |
Number.MAX_SAFE_INTEGER | 2⁵³ − 1 = 9007199254740991 | Number.MAX_SAFE_INTEGER |
Number.EPSILON | Smallest float difference ≈ 2.2e-16 | Number.EPSILON |
n.toFixed(d) | String with d decimal places | (1.005).toFixed(2) → "1.00" |
n.toPrecision(d) | String with d significant digits | (123.45).toPrecision(4) → "123.5" |
n.toString(radix?) | Number as string, optional base | (255).toString(16) → "ff" |
String (MDN →)
| Method / Property | Description | Example → result |
|---|---|---|
s.length | Character count | "abc".length → 3 |
s.toUpperCase() | All uppercase | "abc".toUpperCase() → "ABC" |
s.toLowerCase() | All lowercase | "ABC".toLowerCase() → "abc" |
s.trim() | Remove leading/trailing whitespace | " hi ".trim() → "hi" |
s.includes(sub) | true if substring present | "shelf".includes("el") → true |
s.startsWith(sub) | true if starts with sub | "shelf".startsWith("sh") → true |
s.endsWith(sub) | true if ends with sub | "shelf".endsWith("lf") → true |
s.indexOf(sub) | Position of first match, -1 if none | "shelf".indexOf("e") → 2 |
s.slice(start, end?) | Extract [start, end) | "shelf".slice(1,3) → "he" |
s.replace(a, b) | Replace first occurrence | "aab".replace("a","x") → "xab" |
s.replaceAll(a, b) | Replace all occurrences | "aab".replaceAll("a","x") → "xxb" |
s.split(sep) | Split into array | "a,b".split(",") → ["a","b"] |
s.repeat(n) | Repeat n times | "ab".repeat(3) → "ababab" |
s.padStart(len, ch) | Pad left to length | "5".padStart(3,"0") → "005" |
s.padEnd(len, ch) | Pad right to length | "5".padEnd(3,"0") → "500" |
Array (MDN →)
| Method / Property | Description | Example → result |
|---|---|---|
arr.length | Number of elements | [1,2,3].length → 3 |
arr.map(fn) | New array: fn applied to each element | [1,2,3].map(x=>x*2) → [2,4,6] |
arr.filter(fn) | New array: only elements where fn is true | [1,2,3].filter(x=>x>1) → [2,3] |
arr.reduce(fn, init) | Fold to single value | [1,2,3].reduce((a,b)=>a+b,0) → 6 |
arr.find(fn) | First element where fn is true | [1,2,3].find(x=>x>1) → 2 |
arr.findIndex(fn) | Index of first match, -1 if none | [1,2,3].findIndex(x=>x>1) → 1 |
arr.some(fn) | true if any element passes fn | [1,2,3].some(x=>x>2) → true |
arr.every(fn) | true if all elements pass fn | [1,2,3].every(x=>x>0) → true |
arr.includes(v) | true if value exists in array | [1,2,3].includes(2) → true |
arr.indexOf(v) | Index of first match, -1 if none | [1,2,3].indexOf(2) → 1 |
arr.slice(s, e?) | Copy subarray [s, e) | [1,2,3].slice(1) → [2,3] |
arr.concat(b) | Join two arrays (non-mutating) | [1,2].concat([3,4]) → [1,2,3,4] |
arr.join(sep) | Join elements as string | [1,2,3].join("-") → "1-2-3" |
arr.flat(depth?) | Flatten nested arrays | [[1,2],[3]].flat() → [1,2,3] |
arr.flatMap(fn) | map then flat(1) | [1,2].flatMap(x=>[x,x*2]) → [1,2,2,4] |
arr.sort(fn?) | Sort (pass (a,b)=>a-b for numbers) | [3,1,2].sort((a,b)=>a-b) → [1,2,3] |
arr.reverse() | Reverse in place | [1,2,3].reverse() → [3,2,1] |
Array.from({length:n}, fn) | Create array of length n via fn(_, i) | Array.from({length:3},(_,i)=>i) → [0,1,2] |
Array.isArray(v) | true if value is an array | Array.isArray([1,2]) → true |
Object (MDN →)
| Method | Description | Example → result |
|---|---|---|
Object.keys(obj) | Array of own property keys | Object.keys({a:1,b:2}) → ["a","b"] |
Object.values(obj) | Array of own property values | Object.values({a:1,b:2}) → [1,2] |
Object.entries(obj) | Array of [key, value] pairs | Object.entries({a:1}) → [["a",1]] |
Object.assign(target, src) | Copy src properties into target | Object.assign({a:1},{b:2}) → {a:1,b:2} |
Object.fromEntries(pairs) | Build object from [[key,val], …] | Object.fromEntries([["a",1]]) → {a:1} |
parseInt · parseFloat · isNaN · Boolean (MDN →)
| Function | Description | Example → result |
|---|---|---|
parseInt(s, radix?) | Parse integer from string (radix default 10) | parseInt("42px") → 42 |
parseFloat(s) | Parse float from string | parseFloat("3.14abc") → 3.14 |
isNaN(v) | true if NaN after coercion | isNaN("abc") → true |
Boolean(v) | Falsy: 0 "" null undefined NaN | Boolean(0) → false |
Selecting faces & edges
Edge Fillet, Face Extrude etc. take a filter arrow instead of an index:
(points, normal) => normal[2] > 0.9 // Face Extrude — only the top
(p1, p2) => p1[2] > 0 && p2[2] > 0 // Edge Fillet — only top edgesNot supported
| Not available | Use instead |
|---|---|
if … else | cond ? a : b |
for / while | arr.map / filter / reduce |
function () {} | x => x * 2 |
let / const / = | read-only — no assignment |
...spread ?? \template`` | not parsed by the expression engine |
console · Date · RegExp · JSON | not in scope |