Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(editor): Add examples for number & boolean, add new methods #9358

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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$ ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down
26 changes: 16 additions & 10 deletions packages/workflow/src/Extensions/BooleanExtensions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ExtensionMap } from './Extensions';
import type { Extension, ExtensionMap } from './Extensions';

export function toBoolean(value: boolean) {
return value;
Expand All @@ -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 <code>true</code> to <code>1</code> and <code>false</code> to <code>0</code>.',
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 = {
Expand All @@ -30,6 +35,7 @@ export const booleanExtensions: ExtensionMap = {
toBoolean,
toInt,
toFloat,
toNumber,
toDateTime,
elsmr marked this conversation as resolved.
Show resolved Hide resolved
},
};
125 changes: 112 additions & 13 deletions packages/workflow/src/Extensions/NumberExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -86,56 +94,106 @@ 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 <code>true</code> if the number is even or <code>false</code> 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 <code>true</code> if the number is odd or <code>false</code> 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',
};

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 <a target="_blank" href=”https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat”><code>Intl.NumberFormat()</code></a>.',
examples: [
{ example: "(123456.789).format('de-DE')", evaluated: '123.456,789' },
{
example: "(123456.789).format('de-DE', {'style': 'currency', 'currency': 'EUR'})",
elsmr marked this conversation as resolved.
Show resolved Hide resolved
evaluated: '123.456,79 €',
},
],
returnType: 'string',
args: [
{ name: 'locales?', type: 'LanguageCode' },
{ name: 'options?', type: 'FormatOptions' },
{
name: 'locale',
optional: true,
description:
'A <a target="_blank" href=”https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument”>locale tag</a> for formatting the number, e.g. <code>fr-FR</code>, <code>en-GB</code>, <code>pr-BR</code>',
default: '"en-US"',
type: 'string',
},
{
name: 'options',
optional: true,
description:
'Configuration options for number formatting. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat" target="_blank">More info</a>',
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 <code>false</code> for <code>0</code> and <code>true</code> 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:
Expand All @@ -145,21 +203,62 @@ 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 <a target="_blank" href="https://moment.github.io/luxon/api-docs/">Luxon</a> 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 <code>ms</code> (for Unix timestamp in milliseconds), <code>s</code> (for Unix timestamp in seconds), <code>us</code> (for Unix timestamp in microseconds) or <code>excel</code> (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 <code>true</code> if the number is a whole number',
examples: [
{ example: '(4).isInteger()', evaluated: 'true' },
{ example: '(4.12).isInteger()', evaluated: 'false' },
elsmr marked this conversation as resolved.
Show resolved Hide resolved
{ 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: {
ceil,
floor,
format,
round,
abs,
isInteger,
isEven,
isOdd,
toBoolean,
Expand Down
2 changes: 1 addition & 1 deletion packages/workflow/src/Extensions/StringExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a target="_blank" href=”https://moment.github.io/luxon/api-docs/index.html#datetimefromformat”> <code>DateTime.fromFormat()</code></a>.',
'Converts the string to a <a target="_blank" href="https://moment.github.io/luxon/api-docs/">Luxon</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 <a target="_blank" href=”https://moment.github.io/luxon/api-docs/index.html#datetimefromformat”> <code>DateTime.fromFormat()</code></a>.',
section: 'cast',
returnType: 'DateTime',
docURL:
Expand Down
7 changes: 6 additions & 1 deletion packages/workflow/src/NativeMethods/Boolean.methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export const booleanMethods: NativeDoc = {
toString: {
doc: {
name: 'toString',
description: 'returns a string representing this boolean value.',
description:
"Converts <code>true</code> to the string <code>'true'</code> and <code>false</code> to the string <code>'false'</code>.",
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',
Expand Down
49 changes: 47 additions & 2 deletions packages/workflow/src/NativeMethods/Number.methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>toLocaleString()</code>.',
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 <code>2</code> is binary and base <code>16</code> 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 <a target="_blank" href="https://www.localeplanet.com/icu/">full list</a> (unofficial). Also accepts an <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument">array of locales</a>. Defaults to the system locale if not specified.',
type: 'string | string[]',
},
{
name: 'options',
optional: true,
description:
'An object with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters">formatting options</a>',
type: 'object',
},
],
returnType: 'string',
},
},
Expand Down
Loading