feat(editor): Autocomplete info box: improve structure and add examples (#9019)

Co-authored-by: Giulio Andreini <andreini@netseven.it>
This commit is contained in:
Elias Meire
2024-05-10 14:39:06 +02:00
committed by GitHub
parent 4ed585040b
commit c92c870c73
30 changed files with 1596 additions and 457 deletions

View File

@@ -1,6 +1,6 @@
import { ExpressionError } from '../errors/expression.error';
import { ExpressionExtensionError } from '../errors/expression-extension.error';
import type { ExtensionMap } from './Extensions';
import type { Extension, ExtensionMap } from './Extensions';
import { compact as oCompact } from './ObjectExtensions';
import deepEqual from 'deep-equal';
@@ -511,10 +511,13 @@ toJsonString.doc = {
returnType: 'string',
};
const removeDuplicates: Extension = unique.bind({});
removeDuplicates.doc = { ...unique.doc, hidden: true };
export const arrayExtensions: ExtensionMap = {
typeName: 'Array',
functions: {
removeDuplicates: unique,
removeDuplicates,
unique,
first,
last,

View File

@@ -286,7 +286,7 @@ format.doc = {
description: 'Formats a Date in the given structure.',
returnType: 'string',
section: 'format',
args: [{ name: 'fmt', default: 'yyyy-MM-dd', type: 'TimeFormat' }],
args: [{ name: 'fmt', default: "'yyyy-MM-dd'", type: 'TimeFormat' }],
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-format',
};
@@ -304,6 +304,7 @@ isBetween.doc = {
isInLast.doc = {
name: 'isInLast',
hidden: true,
description: 'Checks if a Date is within a given time period. Default unit is `minute`.',
section: 'query',
returnType: 'boolean',
@@ -317,7 +318,6 @@ isInLast.doc = {
toDateTime.doc = {
name: 'toDateTime',
description: 'Convert a JavaScript Date to a Luxon DateTime.',
section: 'query',
returnType: 'DateTime',
hidden: true,
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-toDateTime',

View File

@@ -16,6 +16,7 @@ import type { ExpressionKind } from 'ast-types/gen/kinds';
import type { ExpressionChunk, ExpressionCode } from './ExpressionParser';
import { joinExpression, splitExpression } from './ExpressionParser';
import { booleanExtensions } from './BooleanExtensions';
import type { ExtensionMap } from './Extensions';
const EXPRESSION_EXTENDER = 'extend';
const EXPRESSION_EXTENDER_OPTIONAL = 'extendOptional';
@@ -28,7 +29,7 @@ function isNotEmpty(value: unknown) {
return !isEmpty(value);
}
export const EXTENSION_OBJECTS = [
export const EXTENSION_OBJECTS: ExtensionMap[] = [
arrayExtensions,
dateExtensions,
numberExtensions,

View File

@@ -12,6 +12,20 @@ export type NativeDoc = {
functions: Record<string, { doc?: DocMetadata }>;
};
export type DocMetadataArgument = {
name: string;
type?: string;
optional?: boolean;
variadic?: boolean;
description?: string;
default?: string;
};
export type DocMetadataExample = {
example: string;
evaluated?: string;
description?: string;
};
export type DocMetadata = {
name: string;
returnType: string;
@@ -19,6 +33,7 @@ export type DocMetadata = {
section?: string;
hidden?: boolean;
aliases?: string[];
args?: Array<{ name: string; type?: string }>;
args?: DocMetadataArgument[];
examples?: DocMetadataExample[];
docURL?: string;
};

View File

@@ -53,10 +53,16 @@ function toFloat(value: number) {
return value;
}
type DateTimeFormat = 'ms' | 's' | 'excel';
type DateTimeFormat = 'ms' | 's' | 'us' | 'excel';
function toDateTime(value: number, extraArgs: [DateTimeFormat]) {
const [valueFormat = 'ms'] = extraArgs;
if (!['ms', 's', 'us', 'excel'].includes(valueFormat)) {
throw new ExpressionExtensionError(
`Unsupported format '${String(valueFormat)}'. toDateTime() supports 'ms', 's', 'us' and 'excel'.`,
);
}
switch (valueFormat) {
// Excel format is days since 1900
// There is a bug where 1900 is incorrectly treated as a leap year
@@ -70,6 +76,8 @@ function toDateTime(value: number, extraArgs: [DateTimeFormat]) {
}
case 's':
return DateTime.fromSeconds(value);
case 'us':
return DateTime.fromMillis(value / 1000);
case 'ms':
default:
return DateTime.fromMillis(value);
@@ -107,7 +115,7 @@ 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 like format `1.234`.',
'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`.',
returnType: 'string',
args: [
{ name: 'locales?', type: 'LanguageCode' },
@@ -137,7 +145,7 @@ toBoolean.doc = {
toDateTime.doc = {
name: 'toDateTime',
description:
"Converts a number to a DateTime. Defaults to milliseconds. Format can be 'ms' (milliseconds), 's' (seconds) or 'excel' (Excel 1900 format).",
"Converts a number to a DateTime. Defaults to milliseconds. Format can be 'ms' (milliseconds), 's' (seconds), 'us' (microseconds) or 'excel' (Excel 1900 format).",
section: 'cast',
returnType: 'DateTime',
args: [{ name: 'format?', type: 'string' }],

View File

@@ -265,6 +265,16 @@ function toFloat(value: string) {
return float;
}
function toNumber(value: string) {
const num = Number(value.replace(CURRENCY_REGEXP, ''));
if (isNaN(num)) {
throw new ExpressionExtensionError('cannot convert to number');
}
return num;
}
function quote(value: string, extraArgs: string[]) {
const [quoteChar = '"'] = extraArgs;
return `${quoteChar}${value
@@ -405,20 +415,22 @@ function base64Decode(value: string): string {
removeMarkdown.doc = {
name: 'removeMarkdown',
description: 'Removes Markdown formatting from a string.',
description: 'Removes any Markdown formatting from the string. Also removes HTML tags.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-removeMarkdown',
examples: [{ example: '"*bold*, [link]()".removeMarkdown()', evaluated: '"bold, link"' }],
};
removeTags.doc = {
name: 'removeTags',
description: 'Removes tags, such as HTML or XML, from a string.',
description: 'Removes tags, such as HTML or XML, from the string.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-removeTags',
examples: [{ example: '"<b>bold</b>, <a>link</a>".removeTags()', evaluated: '"bold, link"' }],
};
toDate.doc = {
@@ -432,20 +444,34 @@ toDate.doc = {
toDateTime.doc = {
name: 'toDateTime',
description: 'Converts a string to a Luxon DateTime.',
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>.',
section: 'cast',
returnType: 'DateTime',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toDateTime',
examples: [
{ example: '"2024-03-29T18:06:31.798+01:00".toDateTime()' },
{ example: '"Fri, 29 Mar 2024 18:08:01 +0100".toDateTime()' },
{ example: '"20240329".toDateTime()' },
{ example: '"1711732132990".toDateTime()' },
],
};
toBoolean.doc = {
name: 'toBoolean',
description: 'Converts a string to a boolean.',
description:
'Converts the string to a boolean value. <code>0</code>, <code>false</code> and <code>no</code> resolve to <code>false</code>, everything else to <code>true</code>. Case-insensitive.',
section: 'cast',
returnType: 'boolean',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toBoolean',
examples: [
{ example: '"true".toBoolean()', evaluated: 'true' },
{ example: '"false".toBoolean()', evaluated: 'false' },
{ example: '"0".toBoolean()', evaluated: 'false' },
{ example: '"hello".toBoolean()', evaluated: 'true' },
],
};
toFloat.doc = {
@@ -454,6 +480,7 @@ toFloat.doc = {
section: 'cast',
returnType: 'number',
aliases: ['toDecimalNumber'],
hidden: true,
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toDecimalNumber',
};
@@ -465,12 +492,15 @@ toInt.doc = {
returnType: 'number',
args: [{ name: 'radix?', type: 'number' }],
aliases: ['toWholeNumber'],
hidden: true,
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toInt',
};
toSentenceCase.doc = {
name: 'toSentenceCase',
description: 'Formats a string to sentence case. Example: "This is a sentence".',
description:
'Changes the capitalization of the string to sentence case. The first letter of each sentence is capitalized and all others are lowercased.',
examples: [{ example: '"quick! brown FOX".toSentenceCase()', evaluated: '"Quick! Brown fox"' }],
section: 'case',
returnType: 'string',
docURL:
@@ -479,7 +509,9 @@ toSentenceCase.doc = {
toSnakeCase.doc = {
name: 'toSnakeCase',
description: 'Formats a string to snake case. Example: "this_is_snake_case".',
description:
'Changes the format of the string to snake case. Spaces and dashes are replaced by <code>_</code>, symbols are removed and all letters are lowercased.',
examples: [{ example: '"quick brown $FOX".toSnakeCase()', evaluated: '"quick_brown_fox"' }],
section: 'case',
returnType: 'string',
docURL:
@@ -489,7 +521,8 @@ toSnakeCase.doc = {
toTitleCase.doc = {
name: 'toTitleCase',
description:
'Formats a string to title case. Example: "This Is a Title". Will not change already uppercase letters to prevent losing information from acronyms and trademarks such as iPhone or FAANG.',
"Changes the capitalization of the string to title case. The first letter of each word is capitalized and the others left unchanged. Short prepositions and conjunctions aren't capitalized (e.g. 'a', 'the').",
examples: [{ example: '"quick a brown FOX".toTitleCase()', evaluated: '"Quick a Brown Fox"' }],
section: 'case',
returnType: 'string',
docURL:
@@ -498,31 +531,60 @@ toTitleCase.doc = {
urlEncode.doc = {
name: 'urlEncode',
description: 'Encodes a string to be used/included in a URL.',
description:
'Encodes the string so that it can be used in a URL. Spaces and special characters are replaced with codes of the form <code>%XX</code>.',
section: 'edit',
args: [{ name: 'entireString?', type: 'boolean' }],
args: [
{
name: 'allChars',
optional: true,
description:
'Whether to encode characters that are part of the URI syntax (e.g. <code>=</code>, <code>?</code>)',
default: 'false',
type: 'boolean',
},
],
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-urlEncode',
examples: [
{ example: '"name=Nathan Automat".urlEncode()', evaluated: '"name%3DNathan%20Automat"' },
{ example: '"name=Nathan Automat".urlEncode(true)', evaluated: '"name=Nathan%20Automat"' },
],
};
urlDecode.doc = {
name: 'urlDecode',
description:
'Decodes a URL-encoded string. It decodes any percent-encoded characters in the input string, and replaces them with their original characters.',
'Decodes a URL-encoded string. Replaces any character codes in the form of <code>%XX</code> with their corresponding characters.',
args: [
{
name: 'allChars',
optional: true,
description:
'Whether to decode characters that are part of the URI syntax (e.g. <code>=</code>, <code>?</code>)',
default: 'false',
type: 'boolean',
},
],
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-urlDecode',
examples: [
{ example: '"name%3DNathan%20Automat".urlDecode()', evaluated: '"name=Nathan Automat"' },
{ example: '"name%3DNathan%20Automat".urlDecode(true)', evaluated: '"name%3DNathan Automat"' },
],
};
replaceSpecialChars.doc = {
name: 'replaceSpecialChars',
description: 'Replaces non-ASCII characters in a string with an ASCII representation.',
description: 'Replaces special characters in the string with the closest ASCII character',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-replaceSpecialChars',
examples: [{ example: '"déjà".replaceSpecialChars()', evaluated: '"deja"' }],
};
length.doc = {
@@ -536,122 +598,199 @@ length.doc = {
isDomain.doc = {
name: 'isDomain',
description: 'Checks if a string is a domain.',
description: 'Returns <code>true</code> if a string is a domain.',
section: 'validation',
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isDomain',
examples: [
{ example: '"n8n.io".isDomain()', evaluated: 'true' },
{ example: '"http://n8n.io".isDomain()', evaluated: 'false' },
{ example: '"hello".isDomain()', evaluated: 'false' },
],
};
isEmail.doc = {
name: 'isEmail',
description: 'Checks if a string is an email.',
description: 'Returns <code>true</code> if the string is an email.',
section: 'validation',
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isEmail',
examples: [
{ example: '"me@example.com".isEmail()', evaluated: 'true' },
{ example: '"It\'s me@example.com".isEmail()', evaluated: 'false' },
{ example: '"hello".isEmail()', evaluated: 'false' },
],
};
isNumeric.doc = {
name: 'isNumeric',
description: 'Checks if a string only contains digits.',
description: 'Returns <code>true</code> if the string represents a number.',
section: 'validation',
returnType: 'boolean',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isNumeric',
examples: [
{ example: '"1.2234".isNumeric()', evaluated: 'true' },
{ example: '"hello".isNumeric()', evaluated: 'false' },
{ example: '"123E23".isNumeric()', evaluated: 'true' },
],
};
isUrl.doc = {
name: 'isUrl',
description: 'Checks if a string is a valid URL.',
description: 'Returns <code>true</code> if a string is a valid URL',
section: 'validation',
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isUrl',
examples: [
{ example: '"https://n8n.io".isUrl()', evaluated: 'true' },
{ example: '"n8n.io".isUrl()', evaluated: 'false' },
{ example: '"hello".isUrl()', evaluated: 'false' },
],
};
isEmpty.doc = {
name: 'isEmpty',
description: 'Checks if a string is empty.',
description: 'Returns <code>true</code> if the string has no characters.',
section: 'validation',
returnType: 'boolean',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isEmpty',
examples: [
{ example: '"".isEmpty()', evaluated: 'true' },
{ example: '"hello".isEmpty()', evaluated: 'false' },
],
};
isNotEmpty.doc = {
name: 'isNotEmpty',
description: 'Checks if a string has content.',
description: 'Returns <code>true</code> if the string has at least one character.',
section: 'validation',
returnType: 'boolean',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isNotEmpty',
examples: [
{ example: '"hello".isNotEmpty()', evaluated: 'true' },
{ example: '"".isNotEmpty()', evaluated: 'false' },
],
};
extractEmail.doc = {
name: 'extractEmail',
description: 'Extracts an email from a string. Returns undefined if none is found.',
description:
'Extracts the first email found in the string. Returns <code>undefined</code> if none is found.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractEmail',
examples: [
{ example: '"My email is me@example.com".extractEmail()', evaluated: "'me@example.com'" },
],
};
extractDomain.doc = {
name: 'extractDomain',
description:
'Extracts a domain from a string containing a valid URL. Returns undefined if none is found.',
'If the string is an email address or URL, returns its domain (or <code>undefined</code> if nothing found). If the string also contains other content, try using <code>extractEmail()</code> or <code>extractUrl()</code> first.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractDomain',
examples: [
{ example: '"me@example.com".extractDomain()', evaluated: "'example.com'" },
{ example: '"http://n8n.io/workflows".extractDomain()', evaluated: "'n8n.io'" },
{
example: '"It\'s me@example.com".extractEmail().extractDomain()',
evaluated: "'example.com'",
},
],
};
extractUrl.doc = {
name: 'extractUrl',
description: 'Extracts a URL from a string. Returns undefined if none is found.',
description:
'Extracts the first URL found in the string. Returns <code>undefined</code> if none is found. Only recognizes full URLs, e.g. those starting with <code>http</code>.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractUrl',
examples: [{ example: '"Check out http://n8n.io".extractUrl()', evaluated: "'http://n8n.io'" }],
};
extractUrlPath.doc = {
name: 'extractUrlPath',
description: 'Extracts the path from a URL. Returns undefined if none is found.',
description:
'Returns the part of a URL after the domain, or <code>undefined</code> if no URL found. If the string also contains other content, try using <code>extractUrl()</code> first.',
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractUrlPath',
examples: [
{ example: '"http://n8n.io/workflows".extractUrlPath()', evaluated: "'/workflows'" },
{
example: '"Check out http://n8n.io/workflows".extractUrl().extractUrlPath()',
evaluated: "'/workflows'",
},
],
};
hash.doc = {
name: 'hash',
description: 'Returns a string hashed with the given algorithm. Default algorithm is `md5`.',
description:
'Returns the string hashed with the given algorithm. Defaults to md5 if not specified.',
section: 'edit',
returnType: 'string',
args: [{ name: 'algo?', type: 'Algorithm' }],
args: [
{
name: 'algo',
optional: true,
description:
'The hashing algorithm to use. One of <code>md5</code>, <code>base64</code>, <code>sha1</code>, <code>sha224</code>, <code>sha256</code>, <code>sha384</code>, <code>sha512</code>, <code>sha3</code>, <code>ripemd160</code>\n ',
default: '"md5"',
type: 'string',
},
],
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-hash',
examples: [{ example: '"hello".hash()', evaluated: "'5d41402abc4b2a76b9719d911017c592'" }],
};
quote.doc = {
name: 'quote',
description: 'Returns a string wrapped in the quotation marks. Default quotation is `"`.',
description:
'Wraps a string in quotation marks, and escapes any quotation marks already in the string. Useful when constructing JSON, SQL, etc.',
section: 'edit',
returnType: 'string',
args: [{ name: 'mark?', type: 'string' }],
args: [
{
name: 'mark',
optional: true,
description: 'The type of quotation mark to use',
default: '"',
type: 'string',
},
],
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-quote',
examples: [{ example: '\'Nathan says "hi"\'.quote()', evaluated: '\'"Nathan says \\"hi\\""\'' }],
};
parseJson.doc = {
name: 'parseJson',
description:
'Parses a JSON string, constructing the JavaScript value or object described by the string.',
"Returns the JavaScript value or object represented by the string, or <code>undefined</code> if the string isn't valid JSON. Single-quoted JSON is not supported.",
section: 'cast',
returnType: 'any',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-parseJson',
examples: [
{ example: '\'{"name":"Nathan"}\'.parseJson()', evaluated: '\'{"name":"Nathan"}\'' },
{ example: "\"{'name':'Nathan'}\".parseJson()", evaluated: 'undefined' },
{ example: "'hello'.parseJson()", evaluated: 'undefined' },
],
};
base64Encode.doc = {
name: 'base64Encode',
description: 'Converts a UTF-8-encoded string to a Base64 string.',
description: 'Converts plain text to a base64-encoded string',
examples: [{ example: '"hello".base64Encode()', evaluated: '"aGVsbG8="' }],
section: 'edit',
returnType: 'string',
docURL:
@@ -660,17 +799,29 @@ base64Encode.doc = {
base64Decode.doc = {
name: 'base64Decode',
description: 'Converts a Base64 string to a UTF-8 string.',
description: 'Converts a base64-encoded string to plain text',
examples: [{ example: '"aGVsbG8=".base64Decode()', evaluated: '"hello"' }],
section: 'edit',
returnType: 'string',
docURL:
'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-base64Decode',
};
toNumber.doc = {
name: 'toNumber',
description:
"Converts a string representing a number to a number. Errors if the string doesn't start with a valid number.",
section: 'cast',
returnType: 'number',
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toNumber',
examples: [
{ example: '"123".toNumber()', evaluated: '123' },
{ example: '"1.23E10".toNumber()', evaluated: '12300000000' },
],
};
const toDecimalNumber: Extension = toFloat.bind({});
toDecimalNumber.doc = { ...toFloat.doc, hidden: true };
const toWholeNumber: Extension = toInt.bind({});
toWholeNumber.doc = { ...toInt.doc, hidden: true };
export const stringExtensions: ExtensionMap = {
typeName: 'String',
@@ -682,6 +833,7 @@ export const stringExtensions: ExtensionMap = {
toDateTime,
toBoolean,
toDecimalNumber,
toNumber,
toFloat,
toInt,
toWholeNumber,

View File

@@ -7,4 +7,10 @@ export {
EXTENSION_OBJECTS as ExpressionExtensions,
} from './ExpressionExtension';
export type { DocMetadata, NativeDoc } from './Extensions';
export type {
DocMetadata,
NativeDoc,
Extension,
DocMetadataArgument,
DocMetadataExample,
} from './Extensions';

View File

@@ -53,6 +53,7 @@ export const arrayMethods: NativeDoc = {
findIndex: {
doc: {
name: 'findIndex',
hidden: true,
description:
'Returns the index of the first element in an array that passes the test `fn`. If none are found, -1 is returned.',
docURL:
@@ -64,6 +65,7 @@ export const arrayMethods: NativeDoc = {
findLast: {
doc: {
name: 'findLast',
hidden: true,
description: 'Returns the value of the last element that passes the test `fn`.',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findLast',
@@ -74,6 +76,7 @@ export const arrayMethods: NativeDoc = {
findLastIndex: {
doc: {
name: 'findLastIndex',
hidden: true,
description:
'Returns the index of the last element that satisfies the provided testing function. If none are found, -1 is returned.',
docURL:
@@ -183,6 +186,7 @@ export const arrayMethods: NativeDoc = {
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice',
returnType: 'Array',
hidden: true,
args: [
{ name: 'start', type: 'number' },
{ name: 'deleteCount?', type: 'number' },
@@ -195,11 +199,22 @@ export const arrayMethods: NativeDoc = {
toString: {
doc: {
name: 'toString',
hidden: true,
description: 'Returns a string representing the specified array and its elements.',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString',
returnType: 'string',
},
},
toSpliced: {
doc: {
name: 'toSpliced',
description:
'Returns a new array with some elements removed and/or replaced at a given index. <code>toSpliced()</code> is the copying version of the <code>splice()</code> method',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced',
returnType: 'Array',
},
},
},
};

View File

@@ -29,11 +29,20 @@ export const numberMethods: NativeDoc = {
toString: {
doc: {
name: 'toString',
description: 'returns a string representing this number value.',
description: 'Returns a string representing this number value.',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString',
returnType: 'string',
},
},
toLocaleString: {
doc: {
name: 'toLocaleString',
description: 'Returns a string with a language-sensitive representation of this number.',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString',
returnType: 'string',
},
},
},
};

View File

@@ -6,7 +6,8 @@ export const stringMethods: NativeDoc = {
length: {
doc: {
name: 'length',
description: 'Returns the number of characters in the string.',
description: 'The number of characters in the string',
examples: [{ example: '"hello".length', evaluated: '5' }],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length',
@@ -18,74 +19,208 @@ export const stringMethods: NativeDoc = {
concat: {
doc: {
name: 'concat',
description: 'Concatenates the string arguments to the calling string.',
description:
'Joins one or more strings onto the end of the base string. Alternatively, use the <code>+</code> operator (see examples).',
examples: [
{ example: "'sea'.concat('food')", evaluated: "'seafood'" },
{ example: "'sea' + 'food'", evaluated: "'seafood'" },
{ example: "'work'.concat('a', 'holic')", evaluated: "'workaholic'" },
],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat',
args: [
{
name: 'strings',
optional: false,
variadic: true,
description: 'The strings to append, in order',
type: 'string[]',
},
],
returnType: 'string',
},
},
endsWith: {
doc: {
name: 'endsWith',
description: 'Checks if a string ends with `searchString`.',
description:
'Returns <code>true</code> if the string ends with <code>searchString</code>. Case-sensitive.',
examples: [
{ example: "'team'.endsWith('eam')", evaluated: 'true' },
{ example: "'team'.endsWith('Eam')", evaluated: 'false' },
{
example: "'teaM'.toLowerCase().endsWith('eam')",
evaluated: 'true',
description:
"Returns false if the case doesn't match, so consider using .toLowerCase() first",
},
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith',
returnType: 'boolean',
args: [{ name: 'searchString', type: 'string' }],
args: [
{
name: 'searchString',
optional: false,
description: 'The text to check against the end of the base string',
type: 'string',
},
{
name: 'end',
optional: true,
description: 'The end position (index) to start searching from',
type: 'number',
},
],
},
},
indexOf: {
doc: {
name: 'indexOf',
description: 'Returns the index of the first occurrence of `searchString`.',
description:
'Returns the index (position) of the first occurrence of <code>searchString</code> within the base string, or -1 if not found. Case-sensitive.',
examples: [
{ example: "'steam'.indexOf('tea')", evaluated: '1' },
{ example: "'steam'.indexOf('i')", evaluated: '-1' },
{
example: "'STEAM'.indexOf('tea')",
evaluated: '-1',
description:
"Returns -1 if the case doesn't match, so consider using .toLowerCase() first",
},
{ example: "'STEAM'.toLowerCase().indexOf('tea')", evaluated: '1' },
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf',
returnType: 'number',
args: [
{ name: 'searchString', type: 'string' },
{ name: 'position?', type: 'number' },
{
name: 'searchString',
optional: false,
description: 'The text to search for',
type: 'string',
},
{
name: 'start',
optional: true,
description: 'The position (index) to start searching from',
default: '0',
type: 'number',
},
],
},
},
lastIndexOf: {
doc: {
name: 'lastIndexOf',
description: 'Returns the index of the last occurrence of `searchString`.',
description:
'Returns the index (position) of the last occurrence of <code>searchString</code> within the base string, or -1 if not found. Case-sensitive.',
examples: [
{ example: "'canal'.lastIndexOf('a')", evaluated: '3' },
{ example: "'canal'.lastIndexOf('i')", evaluated: '-1' },
{
example: "'CANAL'.lastIndexOf('a')",
evaluated: '-1',
description:
"Returns -1 if the case doesn't match, so consider using .toLowerCase() first",
},
{ example: "'CANAL'.toLowerCase().lastIndexOf('a')", evaluated: '3' },
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf',
returnType: 'number',
args: [
{ name: 'searchString', type: 'string' },
{ name: 'position?', type: 'number' },
{
name: 'searchString',
optional: false,
description: 'The text to search for',
type: 'string',
},
{
name: 'end',
optional: true,
description: 'The position (index) to stop searching at',
default: '0',
type: 'number',
},
],
},
},
match: {
doc: {
name: 'match',
description: 'Retrieves the result of matching a string against a regular expression.',
description:
'Matches the string against a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a>. Returns an array containing the first match, or all matches if the <code>g</code> flag is set in the regular expression. Returns <code>null</code> if no matches are found. \n\nFor checking whether text is present, consider <code>includes()</code> instead.',
examples: [
{
example: '"rock and roll".match(/r[^ ]*/g)',
evaluated: "['rock', 'roll']",
description: "Match all words starting with 'r'",
},
{
example: '"rock and roll".match(/r[^ ]*/)',
evaluated: "['rock']",
description: "Match first word starting with 'r' (no 'g' flag)",
},
{
example: '"ROCK and roll".match(/r[^ ]*/ig)',
evaluated: "['ROCK', 'roll']",
description: "For case-insensitive, add 'i' flag",
},
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match',
returnType: 'Array',
args: [{ name: 'regexp', type: 'string|RegExp' }],
returnType: 'string[]',
args: [
{
name: 'regexp',
optional: false,
description:
'A <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a> with the pattern to look for. Will look for multiple matches if the <code>g</code> flag is present (see examples).',
type: 'RegExp',
},
],
},
},
includes: {
doc: {
name: 'includes',
description: 'Checks if `searchString` may be found within the calling string.',
description:
'Returns <code>true</code> if the string contains the <code>searchString</code>. Case-sensitive.',
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes',
returnType: 'boolean',
args: [
{ name: 'searchString', type: 'string' },
{ name: 'position?', type: 'number' },
{
name: 'searchString',
optional: false,
description: 'The text to search for',
type: 'string',
},
{
name: 'start',
optional: true,
description: 'The position (index) to start searching from',
default: '0',
type: 'number',
},
],
examples: [
{ example: "'team'.includes('tea')", evaluated: 'true' },
{ example: "'team'.includes('i')", evaluated: 'false' },
{
example: "'team'.includes('Tea')",
evaluated: 'false',
description:
"Returns false if the case doesn't match, so consider using .toLowerCase() first",
},
{ example: "'Team'.toLowerCase().includes('tea')", evaluated: 'true' },
],
},
},
@@ -93,54 +228,153 @@ export const stringMethods: NativeDoc = {
doc: {
name: 'replace',
description:
'Returns a string with matches of a `pattern` replaced by a `replacement`. If `pattern` is a string, only the first occurrence will be replaced.',
'Returns a string with the first occurrence of <code>pattern</code> replaced by <code>replacement</code>. \n\nTo replace all occurrences, use <code>replaceAll()</code> instead.',
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace',
returnType: 'string',
args: [
{ name: 'pattern', type: 'string|RegExp' },
{ name: 'replacement', type: 'string' },
{
name: 'pattern',
optional: false,
description:
'The pattern in the string to replace. Can be a string to match or a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a>.',
type: 'string|RegExp',
},
{
name: 'replacement',
optional: false,
description: 'The new text to replace with',
type: 'string',
},
],
examples: [
{
example: "'Red or blue or green'.replace('or', 'and')",
evaluated: "'Red and blue or green'",
},
{
example:
'let text = "Mr Blue has a blue house and a blue car";\ntext.replace(/blue/gi, "red");',
evaluated: "'Mr red has a red house and a red car'",
description: 'A global, case-insensitive replacement:',
},
{
example:
'let text = "Mr Blue has a blue house and a blue car";\ntext.replace(/blue|house|car/gi, (t) => t.toUpperCase());',
evaluated: "'Mr BLUE has a BLUE HOUSE and a BLUE CAR'",
description: 'A function to return the replacement text:',
},
],
},
},
replaceAll: {
doc: {
name: 'replaceAll',
description: 'Returns a string with matches of a `pattern` replaced by a `replacement`.',
description:
'Returns a string with all occurrences of <code>pattern</code> replaced by <code>replacement</code>',
examples: [
{
example: "'Red or blue or green'.replaceAll('or', 'and')",
evaluated: "'Red and blue and green'",
},
{
example:
"text = 'Mr Blue has a blue car';\ntext.replaceAll(/blue|car/gi, t => t.toUpperCase())",
description:
"Uppercase any occurrences of 'blue' or 'car' (You must include the 'g' flag when using a regex)",
evaluated: "'Mr BLUE has a BLUE CAR'",
},
{
example: 'text.replaceAll(/blue|car/gi, function(x){return x.toUpperCase()})',
evaluated: "'Mr BLUE has a BLUE CAR'",
description: 'Or with traditional function notation:',
},
],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll',
returnType: 'string',
args: [
{ name: 'pattern', type: 'string|RegExp' },
{ name: 'replacement', type: 'string' },
{
name: 'pattern',
optional: false,
description:
'The pattern in the string to replace. Can be a string to match or a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a>.',
type: 'string|RegExp',
},
{
name: 'replacement',
optional: false,
description:
'The new text to replace with. Can be a string or a function that returns a string (see examples).',
type: 'string|Function',
},
],
},
},
search: {
doc: {
name: 'search',
description: 'Returns a string that matches `pattern` within the given string.',
description:
'Returns the index (position) of the first occurrence of a pattern within the string, or -1 if not found. The pattern is specified using a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a>. To use text instead, see <code>indexOf()</code>.',
examples: [
{
example: '"Neat n8n node".search(/n[^ ]*/)',
evaluated: '5',
description: "Pos of first word starting with 'n'",
},
{
example: '"Neat n8n node".search(/n[^ ]*/i)',
evaluated: '0',
description:
"Case-insensitive match with 'i'\nPos of first word starting with 'n' or 'N'",
},
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search',
returnType: 'string',
args: [{ name: 'pattern', type: 'string|RegExp' }],
args: [
{
name: 'regexp',
optional: false,
description:
'A <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions">regular expression</a> with the pattern to look for',
type: 'RegExp',
},
],
},
},
slice: {
doc: {
name: 'slice',
description:
'Returns a section of a string. `indexEnd` defaults to the length of the string if not given.',
'Extracts a fragment of the string at the given position. For more advanced extraction, see <code>match()</code>.',
examples: [
{ example: "'Hello from n8n'.slice(0, 5)", evaluated: "'Hello'" },
{ example: "'Hello from n8n'.slice(6)", evaluated: "'from n8n'" },
{ example: "'Hello from n8n'.slice(-3)", evaluated: "'n8n'" },
],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice',
returnType: 'string',
args: [
{ name: 'indexStart', type: 'number' },
{ name: 'indexEnd?', type: 'number' },
{
name: 'start',
optional: false,
description:
'The position to start from. Positions start at 0. Negative numbers count back from the end of the string.',
type: 'number',
},
{
name: 'end',
optional: true,
description:
'The position to select up to. The character at the end position is not included. Negative numbers select from the end of the string. If omitted, will extract to the end of the string.',
type: 'string',
},
],
},
},
@@ -148,28 +382,71 @@ export const stringMethods: NativeDoc = {
doc: {
name: 'split',
description:
'Returns the substrings that result from dividing the given string with `separator`.',
"Splits the string into an array of substrings. Each split is made at the <code>separator</code>, and the separator isn't included in the output. \n\nThe opposite of using <code>join()</code> on an array.",
examples: [
{ example: '"wind,fire,water".split(",")', evaluated: "['wind', 'fire', 'water']" },
{ example: '"me and you and her".split("and")', evaluated: "['me ', ' you ', ' her']" },
{
example: '"me? you, and her".split(/[ ,?]+/)',
evaluated: "['me', 'you', 'and', 'her']",
description: "Split one or more of space, comma and '?' using a regular expression",
},
],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split',
returnType: 'Array',
returnType: 'string[]',
args: [
{ name: 'separator', type: 'string|RegExp' },
{ name: 'limit?', type: 'number' },
{
name: 'separator',
optional: true,
description:
'The string (or regular expression) to use for splitting. If omitted, an array with the original string is returned.',
type: 'string',
},
{
name: 'limit',
optional: true,
description:
'The max number of array elements to return. Returns all elements if omitted.',
type: 'number',
},
],
},
},
startsWith: {
doc: {
name: 'startsWith',
description: 'Checks if the string begins with `searchString`.',
description:
'Returns <code>true</code> if the string starts with <code>searchString</code>. Case-sensitive.',
examples: [
{ example: "'team'.startsWith('tea')", evaluated: 'true' },
{ example: "'team'.startsWith('Tea')", evaluated: 'false' },
{
example: "'Team'.toLowerCase().startsWith('tea')",
evaluated: 'true',
description:
"Returns false if the case doesn't match, so consider using .toLowerCase() first",
},
],
section: 'query',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith',
returnType: 'boolean',
args: [
{ name: 'searchString', type: 'string' },
{ name: 'position?', type: 'number' },
{
name: 'searchString',
optional: false,
description: 'The text to check against the start of the base string',
type: 'string',
},
{
name: 'start',
optional: true,
description: 'The position (index) to start searching from',
default: '0',
type: 'number',
},
],
},
},
@@ -177,31 +454,48 @@ export const stringMethods: NativeDoc = {
doc: {
name: 'substring',
description:
'Returns the part of the string from the start index up to and excluding the end index, or to the end of the string if no end index is supplied.',
'Extracts a fragment of the string at the given position. For more advanced extraction, see <code>match()</code>.',
examples: [
{ example: "'Hello from n8n'.substring(0, 5)", evaluated: "'Hello'" },
{ example: "'Hello from n8n'.substring(6)", evaluated: "'from n8n'" },
],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring',
returnType: 'string',
args: [
{ name: 'indexStart', type: 'number' },
{ name: 'indexEnd?', type: 'number' },
{
name: 'start',
optional: false,
description: 'The position to start from. Positions start at 0.',
type: 'number',
},
{
name: 'end',
optional: true,
description:
'The position to select up to. The character at the end position is not included. If omitted, will extract to the end of the string.',
type: 'string',
},
],
},
},
toLowerCase: {
doc: {
name: 'toLowerCase',
description: 'Formats a string to lowercase. Example: "this is lowercase”.',
description: 'Converts all letters in the string to lower case',
section: 'case',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase',
returnType: 'string',
examples: [{ example: '"I\'m SHOUTing".toLowerCase()', evaluated: '"i\'m shouting"' }],
},
},
toUpperCase: {
doc: {
name: 'toUpperCase',
description: 'Formats a string to lowercase. Example: "THIS IS UPPERCASE”.',
description: 'Converts all letters in the string to upper case (capitals)',
examples: [{ example: '"I\'m not angry".toUpperCase()', evaluated: '"I\'M NOT ANGRY"' }],
section: 'case',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase',
@@ -211,7 +505,9 @@ export const stringMethods: NativeDoc = {
trim: {
doc: {
name: 'trim',
description: 'Removes whitespace from both ends of a string and returns a new string.',
description:
'Removes whitespace from both ends of the string. Whitespace includes new lines, tabs, spaces, etc.',
examples: [{ example: "' lonely '.trim()", evaluated: "'lonely'" }],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim',
@@ -221,7 +517,9 @@ export const stringMethods: NativeDoc = {
trimEnd: {
doc: {
name: 'trimEnd',
description: 'Removes whitespace from the end of a string and returns a new string.',
description:
'Removes whitespace from the end of a string and returns a new string. Whitespace includes new lines, tabs, spaces, etc.',
examples: [{ example: "' lonely '.trimEnd()", evaluated: "' lonely'" }],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd',
@@ -231,7 +529,9 @@ export const stringMethods: NativeDoc = {
trimStart: {
doc: {
name: 'trimStart',
description: 'Removes whitespace from the beginning of a string and returns a new string.',
description:
'Removes whitespace from the beginning of a string and returns a new string. Whitespace includes new lines, tabs, spaces, etc.',
examples: [{ example: "' lonely '.trimStart()", evaluated: "'lonely '" }],
section: 'edit',
docURL:
'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart',

View File

@@ -51,7 +51,13 @@ export * as ExpressionParser from './Extensions/ExpressionParser';
export { NativeMethods } from './NativeMethods';
export * from './NodeParameters/FilterParameter';
export type { DocMetadata, NativeDoc } from './Extensions';
export type {
DocMetadata,
NativeDoc,
DocMetadataArgument,
DocMetadataExample,
Extension,
} from './Extensions';
declare module 'http' {
export interface IncomingMessage {

View File

@@ -77,6 +77,12 @@ describe('Data Transformation Functions', () => {
'2015-05-19T20:00:00.000-04:00',
);
});
test('from microseconds', () => {
expect(evaluate('={{ (1704085200000000).toDateTime("us").toISO() }}')).toEqual(
'2024-01-01T00:00:00.000-05:00',
);
});
});
describe('toInt', () => {