diff --git a/packages/editor-ui/src/plugins/codemirror/completions/__tests__/completions.test.ts b/packages/editor-ui/src/plugins/codemirror/completions/__tests__/completions.test.ts
index 32dd764105f..d1d1ca6d600 100644
--- a/packages/editor-ui/src/plugins/codemirror/completions/__tests__/completions.test.ts
+++ b/packages/editor-ui/src/plugins/codemirror/completions/__tests__/completions.test.ts
@@ -163,6 +163,15 @@ describe('Resolution-based completions', () => {
);
});
+ test('should return completions for boolean literal: {{ true.| }}', () => {
+ // @ts-expect-error Spied function is mistyped
+ vi.spyOn(workflowHelpers, 'resolveParameter').mockReturnValueOnce(true);
+
+ expect(completions('{{ true.| }}')).toHaveLength(
+ natives({ typeName: 'boolean' }).length + extensions({ typeName: 'boolean' }).length,
+ );
+ });
+
test('should properly handle string that contain dollar signs', () => {
// @ts-expect-error Spied function is mistyped
vi.spyOn(workflowHelpers, 'resolveParameter').mockReturnValueOnce("You 'owe' me 200$ ");
diff --git a/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts b/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts
index 5fd734de648..62ab12645da 100644
--- a/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts
+++ b/packages/editor-ui/src/plugins/codemirror/completions/datatype.completions.ts
@@ -847,6 +847,7 @@ const regexes = {
numberLiteral: /\((\d+)\.?(\d*)\)\.(.*)/, // (123). or (123.4).
singleQuoteStringLiteral: /('.*')\.([^'{\s])*/, // 'abc'.
+ booleanLiteral: /(true|false)\.([^'{\s])*/, // true.
doubleQuoteStringLiteral: /(".*")\.([^"{\s])*/, // "abc".
dateLiteral: /\(?new Date\(\(?.*?\)\)?\.(.*)/, // new Date(). or (new Date()).
arrayLiteral: /\(?(\[.*\])\)?\.(.*)/, // [1, 2, 3].
diff --git a/packages/workflow/src/Extensions/BooleanExtensions.ts b/packages/workflow/src/Extensions/BooleanExtensions.ts
index c275c304c94..ad0e3758471 100644
--- a/packages/workflow/src/Extensions/BooleanExtensions.ts
+++ b/packages/workflow/src/Extensions/BooleanExtensions.ts
@@ -1,4 +1,4 @@
-import type { ExtensionMap } from './Extensions';
+import type { Extension, ExtensionMap } from './Extensions';
export function toBoolean(value: boolean) {
return value;
@@ -8,20 +8,25 @@ export function toInt(value: boolean) {
return value ? 1 : 0;
}
-export function toFloat(value: boolean) {
- return value ? 1 : 0;
-}
-
export function toDateTime() {
return undefined;
}
-toInt.doc = {
- name: 'toInt',
- description: 'Converts a boolean to an integer. `false` is 0, `true` is 1.',
+const toFloat = toInt;
+const toNumber: Extension = toInt.bind({});
+
+toNumber.doc = {
+ name: 'toNumber',
+ description:
+ 'Converts true to 1 and false to 0.',
+ examples: [
+ { example: 'true.toNumber()', evaluated: '1' },
+ { example: 'false.toNumber()', evaluated: '0' },
+ ],
section: 'cast',
- returnType: 'boolean',
- docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/booleans/#boolean-toInt',
+ returnType: 'number',
+ docURL:
+ 'https://docs.n8n.io/code/builtin/data-transformation-functions/booleans/#boolean-toNumber',
};
export const booleanExtensions: ExtensionMap = {
@@ -30,6 +35,7 @@ export const booleanExtensions: ExtensionMap = {
toBoolean,
toInt,
toFloat,
+ toNumber,
toDateTime,
},
};
diff --git a/packages/workflow/src/Extensions/NumberExtensions.ts b/packages/workflow/src/Extensions/NumberExtensions.ts
index 58291033cfc..71b86c13734 100644
--- a/packages/workflow/src/Extensions/NumberExtensions.ts
+++ b/packages/workflow/src/Extensions/NumberExtensions.ts
@@ -36,6 +36,14 @@ function ceil(value: number) {
return Math.ceil(value);
}
+function abs(value: number) {
+ return Math.abs(value);
+}
+
+function isInteger(value: number) {
+ return Number.isInteger(value);
+}
+
function round(value: number, extraArgs: number[]) {
const [decimalPlaces = 0] = extraArgs;
return +value.toFixed(decimalPlaces);
@@ -86,28 +94,40 @@ function toDateTime(value: number, extraArgs: [DateTimeFormat]) {
ceil.doc = {
name: 'ceil',
- description: 'Rounds up a number to a whole number.',
+ description: 'Rounds the number up to the next whole number',
+ examples: [{ example: '(1.234).ceil()', evaluated: '2' }],
returnType: 'number',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-ceil',
};
floor.doc = {
name: 'floor',
- description: 'Rounds down a number to a whole number.',
+ description: 'Rounds the number down to the nearest whole number',
+ examples: [{ example: '(1.234).floor()', evaluated: '1' }],
returnType: 'number',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-floor',
};
isEven.doc = {
name: 'isEven',
- description: 'Returns true if the number is even. Only works on whole numbers.',
+ description:
+ "Returns true if the number is even or false if not. Throws an error if the number isn't a whole number.",
+ examples: [
+ { example: '(33).isEven()', evaluated: 'false' },
+ { example: '(42).isEven()', evaluated: 'true' },
+ ],
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isEven',
};
isOdd.doc = {
name: 'isOdd',
- description: 'Returns true if the number is odd. Only works on whole numbers.',
+ description:
+ "Returns true if the number is odd or false if not. Throws an error if the number isn't a whole number.",
+ examples: [
+ { example: '(33).isOdd()', evaluated: 'true' },
+ { example: '(42).isOdd()', evaluated: 'false' },
+ ],
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isOdd',
};
@@ -115,27 +135,65 @@ isOdd.doc = {
format.doc = {
name: 'format',
description:
- 'Returns a formatted string of a number based on the given `LanguageCode` and `FormatOptions`. When no arguments are given, transforms the number in a format like `1.234`.',
+ 'Returns a formatted string representing the number. Useful for formatting for a specific language or currency. The same as Intl.NumberFormat().',
+ examples: [
+ { example: "(123456.789).format('de-DE')", evaluated: '123.456,789' },
+ {
+ example: "(123456.789).format('de-DE', {'style': 'currency', 'currency': 'EUR'})",
+ evaluated: '123.456,79 €',
+ },
+ ],
returnType: 'string',
args: [
- { name: 'locales?', type: 'LanguageCode' },
- { name: 'options?', type: 'FormatOptions' },
+ {
+ name: 'locale',
+ optional: true,
+ description:
+ 'A locale tag for formatting the number, e.g. fr-FR, en-GB, pr-BR',
+ default: '"en-US"',
+ type: 'string',
+ },
+ {
+ name: 'options',
+ optional: true,
+ description:
+ 'Configuration options for number formatting. More info',
+ type: 'object',
+ },
],
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-format',
};
round.doc = {
name: 'round',
- description:
- 'Returns the value of a number rounded to the nearest whole number, unless a decimal place is specified. Defaults to 0 decimal places if no argument is given.',
+ description: 'Rounds the number to the nearest integer (or decimal place)',
+ examples: [
+ { example: '(1.256).round()', evaluated: '1' },
+ { example: '(1.256).round(1)', evaluated: '1.3' },
+ { example: '(1.256).round(2)', evaluated: '1.26' },
+ ],
returnType: 'number',
- args: [{ name: 'decimalPlaces?', type: 'number' }],
+ args: [
+ {
+ name: 'decimalPlaces',
+ optional: true,
+ description: 'The number of decimal places to round to',
+ default: '0',
+ type: 'number',
+ },
+ ],
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-round',
};
toBoolean.doc = {
name: 'toBoolean',
- description: 'Converts a number to a boolean. 0 is `false`, all other numbers are `true`.',
+ description:
+ 'Returns false for 0 and true for any other number (including negative numbers).',
+ examples: [
+ { example: '(12).toBoolean()', evaluated: 'true' },
+ { example: '(0).toBoolean()', evaluated: 'false' },
+ { example: '(-1.3).toBoolean()', evaluated: 'true' },
+ ],
section: 'cast',
returnType: 'boolean',
docURL:
@@ -145,14 +203,53 @@ toBoolean.doc = {
toDateTime.doc = {
name: 'toDateTime',
description:
- "Converts a number to a DateTime. Defaults to milliseconds. Format can be 'ms' (milliseconds), 's' (seconds), 'us' (microseconds) or 'excel' (Excel 1900 format).",
+ 'Converts a numerical timestamp into a Luxon DateTime. The format of the timestamp must be specified if it\'s not in milliseconds. Uses the timezone specified in workflow settings if available; otherwise, it defaults to the timezone set for the instance.',
+ examples: [
+ { example: "(1708695471).toDateTime('s')", evaluated: '2024-02-23T14:37:51.000+01:00' },
+ { example: "(1708695471000).toDateTime('ms')", evaluated: '2024-02-23T14:37:51.000+01:00' },
+ { example: "(1708695471000000).toDateTime('us')", evaluated: '2024-02-23T14:37:51.000+01:00' },
+ { example: "(45345).toDateTime('excel')", evaluated: '2024-02-23T01:00:00.000+01:00' },
+ ],
section: 'cast',
returnType: 'DateTime',
- args: [{ name: 'format?', type: 'string' }],
+ args: [
+ {
+ name: 'format',
+ optional: true,
+ description:
+ 'The type of timestamp to convert. Options are ms (for Unix timestamp in milliseconds), s (for Unix timestamp in seconds), us (for Unix timestamp in microseconds) or excel (for days since 1900).',
+ default: '"ms"',
+ type: 'string',
+ },
+ ],
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-toDateTime',
};
+abs.doc = {
+ name: 'abs',
+ description: "Returns the number's absolute value, i.e. removes any minus sign",
+ examples: [
+ { example: '(-1.7).abs()', evaluated: '1.7' },
+ { example: '(1.7).abs()', evaluated: '1.7' },
+ ],
+ returnType: 'number',
+ docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-abs',
+};
+
+isInteger.doc = {
+ name: 'isInteger',
+ description: 'Returns true if the number is a whole number',
+ examples: [
+ { example: '(4).isInteger()', evaluated: 'true' },
+ { example: '(4.12).isInteger()', evaluated: 'false' },
+ { example: '(-4).isInteger()', evaluated: 'true' },
+ ],
+ returnType: 'boolean',
+ docURL:
+ 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isInteger',
+};
+
export const numberExtensions: ExtensionMap = {
typeName: 'Number',
functions: {
@@ -160,6 +257,8 @@ export const numberExtensions: ExtensionMap = {
floor,
format,
round,
+ abs,
+ isInteger,
isEven,
isOdd,
toBoolean,
diff --git a/packages/workflow/src/Extensions/StringExtensions.ts b/packages/workflow/src/Extensions/StringExtensions.ts
index 9ee944758d3..17e5422c02c 100644
--- a/packages/workflow/src/Extensions/StringExtensions.ts
+++ b/packages/workflow/src/Extensions/StringExtensions.ts
@@ -445,7 +445,7 @@ toDate.doc = {
toDateTime.doc = {
name: 'toDateTime',
description:
- 'Converts the string to a DateTime. Useful for further transformation. Supported formats for the string are ISO 8601, HTTP, RFC2822, SQL and Unix timestamp in milliseconds. To parse other formats, use DateTime.fromFormat().',
+ 'Converts the string to a Luxon DateTime. Useful for further transformation. Supported formats for the string are ISO 8601, HTTP, RFC2822, SQL and Unix timestamp in milliseconds. To parse other formats, use DateTime.fromFormat().',
section: 'cast',
returnType: 'DateTime',
docURL:
diff --git a/packages/workflow/src/NativeMethods/Boolean.methods.ts b/packages/workflow/src/NativeMethods/Boolean.methods.ts
index a6c16ae102c..a897f5dc62f 100644
--- a/packages/workflow/src/NativeMethods/Boolean.methods.ts
+++ b/packages/workflow/src/NativeMethods/Boolean.methods.ts
@@ -6,7 +6,12 @@ export const booleanMethods: NativeDoc = {
toString: {
doc: {
name: 'toString',
- description: 'returns a string representing this boolean value.',
+ description:
+ "Converts true to the string 'true' and false to the string 'false'.",
+ examples: [
+ { example: 'true.toString()', evaluated: "'true'" },
+ { example: 'false.toString()', evaluated: "'false'" },
+ ],
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString',
returnType: 'string',
diff --git a/packages/workflow/src/NativeMethods/Number.methods.ts b/packages/workflow/src/NativeMethods/Number.methods.ts
index 13b418962de..751d68fa7cf 100644
--- a/packages/workflow/src/NativeMethods/Number.methods.ts
+++ b/packages/workflow/src/NativeMethods/Number.methods.ts
@@ -29,18 +29,63 @@ export const numberMethods: NativeDoc = {
toString: {
doc: {
name: 'toString',
- description: 'Returns a string representing this number value.',
+ description:
+ 'Converts the number to a string. For more formatting options, see toLocaleString().',
+ examples: [
+ { example: '(2).toString()', evaluated: "'2'" },
+ { example: '(50.125).toString()', evaluated: "'50.125'" },
+ { example: '(5).toString(2)', evaluated: "'101'" },
+ { example: '(412).toString(16)', evaluated: "'19c'" },
+ ],
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString',
+ args: [
+ {
+ name: 'base',
+ optional: true,
+ description:
+ 'The base to use. Must be an integer between 2 and 36. E.g. base 2 is binary and base 16 is hexadecimal.',
+ default: '10',
+ type: 'number',
+ },
+ ],
returnType: 'string',
},
},
toLocaleString: {
doc: {
name: 'toLocaleString',
- description: 'Returns a string with a language-sensitive representation of this number.',
+ description:
+ "Returns a localized string representing the number, i.e. in the language and format corresponding to its locale. Defaults to the system's locale if none specified.",
+ examples: [
+ {
+ example: '(500000.125).toLocaleString()',
+ evaluated: "'500,000.125' (if in US English locale)",
+ },
+ { example: "(500000.125).toLocaleString('fr-FR')", evaluated: "'500 000,125'" },
+ {
+ example: "(500000.125).toLocaleString('fr-FR', {style:'currency', currency:'EUR'})",
+ evaluated: "'500 000,13 €'",
+ },
+ ],
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString',
+ args: [
+ {
+ name: 'locale(s)',
+ optional: true,
+ description:
+ 'The locale to use, e.g. \'en-GB\' for British English or \'pt-BR\' for Brazilian Portuguese. See full list (unofficial). Also accepts an array of locales. Defaults to the system locale if not specified.',
+ type: 'string | string[]',
+ },
+ {
+ name: 'options',
+ optional: true,
+ description:
+ 'An object with formatting options',
+ type: 'object',
+ },
+ ],
returnType: 'string',
},
},