feat(editor): Add missing documentation to autocomplete items for inline code editor (#5560)

*  Added documentation for extension functions with arguments

*  Adding custom autocomplete item types. This enables us to show different items with same labels.

* 📚 Adding missing info for extensions autocomplete items

*  Added Luxon autocomplete docs

* 💡 Completing Luxon static methods autocomplete documentation

*  Refactoring Luxon autocomplete logic

*  Handling the case when autocomplete item doesn't have defined inline documentation

*  Added correct doc info to Luxon instance properties

*  Added missing documentation and notice footer for autocomplete popup.

* 👕 Fixing lint error

* ✔️ Removing `Object.hasOwn` function, since it's not supported in node v14
This commit is contained in:
Milorad FIlipović
2023-02-28 05:34:03 +01:00
committed by GitHub
parent bb4db58819
commit ae634407a4
15 changed files with 1281 additions and 181 deletions

View File

@@ -14,11 +14,12 @@ import {
stripExcessParens,
} from './utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { ExtensionTypeName, FnToDoc, Resolved } from './types';
import type { AutocompleteOptionType, ExtensionTypeName, FnToDoc, Resolved } from './types';
import { sanitizeHtml } from '@/utils';
import { NativeDoc } from 'n8n-workflow/src/Extensions/Extensions';
type AutocompleteOptionType = 'function' | 'keyword';
import { isFunctionOption } from './typeGuards';
import { luxonInstanceDocs } from './nativesAutocompleteDocs/luxon.instance.docs';
import { luxonStaticDocs } from './nativesAutocompleteDocs/luxon.static.docs';
/**
* Resolution-based completions offered according to datatype.
@@ -59,7 +60,7 @@ export function datatypeCompletions(context: CompletionContext): CompletionResul
if (options.length === 0) return null;
if (tail !== '') {
options = options.filter((o) => prefixMatch(o.label, tail));
options = options.filter((o) => prefixMatch(o.label, tail) && o.label !== tail);
}
return {
@@ -103,7 +104,6 @@ function datatypeOptions(resolved: Resolved, toResolve: string) {
return arrayMethods.filter((m) => !NUMBER_ONLY_ARRAY_EXTENSIONS.has(m.label));
}
return arrayMethods;
}
@@ -120,7 +120,7 @@ export const natives = (typeName: ExtensionTypeName): Completion[] => {
if (!natives) return [];
const nativeProps = natives.properties ? toOptions(natives.properties, typeName, 'keyword') : [];
const nativeMethods = toOptions(natives.functions, typeName, 'function');
const nativeMethods = toOptions(natives.functions, typeName, 'native-function');
return [...nativeProps, ...nativeMethods];
};
@@ -131,78 +131,88 @@ export const extensions = (typeName: ExtensionTypeName) => {
if (!extensions) return [];
const fnToDoc = Object.entries(extensions.functions).reduce<FnToDoc>((acc, [fnName, fn]) => {
if (fn.length !== 1) return acc; // @TODO_NEXT_PHASE: Remove to allow extensions which take args
return { ...acc, [fnName]: { doc: fn.doc } };
}, {});
return toOptions(fnToDoc, typeName);
return toOptions(fnToDoc, typeName, 'extension-function');
};
export const toOptions = (
fnToDoc: FnToDoc,
typeName: ExtensionTypeName,
optionType: AutocompleteOptionType = 'function',
optionType: AutocompleteOptionType = 'native-function',
) => {
return Object.entries(fnToDoc)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([fnName, fn]) => {
const option: Completion = {
label: optionType === 'function' ? fnName + '()' : fnName,
type: optionType,
};
option.info = () => {
const tooltipContainer = document.createElement('div');
tooltipContainer.classList.add('autocomplete-info-container');
if (!fn.doc?.description) return null;
const header =
optionType === 'function'
? createFunctionHeader(typeName, fn)
: createPropHeader(typeName, fn);
header.classList.add('autocomplete-info-header');
tooltipContainer.appendChild(header);
const descriptionBody = document.createElement('div');
descriptionBody.classList.add('autocomplete-info-description');
const descriptionText = document.createElement('p');
descriptionText.innerHTML = sanitizeHtml(
fn.doc.description.replace(/`(.*?)`/g, '<code>$1</code>'),
);
descriptionBody.appendChild(descriptionText);
if (fn.doc.docURL) {
const descriptionLink = document.createElement('a');
descriptionLink.setAttribute('target', '_blank');
descriptionLink.setAttribute('href', fn.doc.docURL);
descriptionLink.innerText = i18n.autocompleteUIValues['docLinkLabel'] || 'Learn more';
descriptionLink.addEventListener('mousedown', (event: MouseEvent) => {
// This will prevent documentation popup closing before click
// event gets to links
event.preventDefault();
});
descriptionLink.classList.add('autocomplete-info-doc-link');
descriptionBody.appendChild(descriptionLink);
}
tooltipContainer.appendChild(descriptionBody);
return tooltipContainer;
};
return option;
return createCompletionOption(typeName, fnName, optionType, fn);
});
};
const createCompletionOption = (
typeName: string,
name: string,
optionType: AutocompleteOptionType,
docInfo: { doc?: DocMetadata | undefined },
): Completion => {
const option: Completion = {
label: isFunctionOption(optionType) ? name + '()' : name,
type: optionType,
};
option.info = () => {
const tooltipContainer = document.createElement('div');
tooltipContainer.classList.add('autocomplete-info-container');
if (!docInfo.doc) return null;
const header = isFunctionOption(optionType)
? createFunctionHeader(typeName, docInfo)
: createPropHeader(typeName, docInfo);
header.classList.add('autocomplete-info-header');
tooltipContainer.appendChild(header);
if (docInfo.doc.description) {
const descriptionBody = document.createElement('div');
descriptionBody.classList.add('autocomplete-info-description');
const descriptionText = document.createElement('p');
descriptionText.innerHTML = sanitizeHtml(
docInfo.doc.description.replace(/`(.*?)`/g, '<code>$1</code>'),
);
descriptionBody.appendChild(descriptionText);
if (docInfo.doc.docURL) {
const descriptionLink = document.createElement('a');
descriptionLink.setAttribute('target', '_blank');
descriptionLink.setAttribute('href', docInfo.doc.docURL);
descriptionLink.innerText = i18n.autocompleteUIValues['docLinkLabel'] || 'Learn more';
descriptionLink.addEventListener('mousedown', (event: MouseEvent) => {
// This will prevent documentation popup closing before click
// event gets to links
event.preventDefault();
});
descriptionLink.classList.add('autocomplete-info-doc-link');
descriptionBody.appendChild(descriptionLink);
}
tooltipContainer.appendChild(descriptionBody);
}
return tooltipContainer;
};
return option;
};
const createFunctionHeader = (typeName: string, fn: { doc?: DocMetadata | undefined }) => {
const header = document.createElement('div');
if (fn.doc) {
const typeNameSpan = document.createElement('span');
typeNameSpan.innerHTML = typeName.slice(0, 1).toUpperCase() + typeName.slice(1) + '.';
header.appendChild(typeNameSpan);
const functionNameSpan = document.createElement('span');
functionNameSpan.classList.add('autocomplete-info-name');
functionNameSpan.innerHTML = `${fn.doc.name}`;
header.appendChild(functionNameSpan);
let functionArgs = '(';
if (fn.doc.args) {
functionArgs += fn.doc.args
@@ -219,14 +229,12 @@ const createFunctionHeader = (typeName: string, fn: { doc?: DocMetadata | undefi
const argsSpan = document.createElement('span');
argsSpan.classList.add('autocomplete-info-name-args');
argsSpan.innerText = functionArgs;
const returnTypeSpan = document.createElement('span');
returnTypeSpan.innerHTML = ': ' + fn.doc.returnType;
header.appendChild(typeNameSpan);
header.appendChild(functionNameSpan);
header.appendChild(argsSpan);
header.appendChild(returnTypeSpan);
if (fn.doc.returnType) {
const returnTypeSpan = document.createElement('span');
returnTypeSpan.innerHTML = ': ' + fn.doc.returnType;
header.appendChild(returnTypeSpan);
}
}
return header;
};
@@ -285,9 +293,18 @@ const objectOptions = (toResolve: string, resolved: IDataObject) => {
};
const infoKey = [name, key].join('.');
const info = i18n.proxyVars[infoKey];
if (info) option.info = info;
option.info = createCompletionOption(
'Object',
key,
isFunction ? 'native-function' : 'keyword',
{
doc: {
name: key,
returnType: typeof resolved[key],
description: i18n.proxyVars[infoKey],
},
},
).info;
return option;
});
@@ -325,17 +342,8 @@ export const luxonInstanceOptions = () => {
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, descriptor]) => {
const isFunction = typeof descriptor.value === 'function';
const option: Completion = {
label: isFunction ? key + '()' : key,
type: isFunction ? 'function' : 'keyword',
};
const info = i18n.luxonInstance[key];
if (info) option.info = info;
return option;
const optionType = isFunction ? 'native-function' : 'keyword';
return createLuxonAutocompleteOption(key, optionType, luxonInstanceDocs, i18n.luxonInstance);
});
};
@@ -349,19 +357,49 @@ export const luxonStaticOptions = () => {
.filter((key) => !SKIP.has(key) && !key.includes('_'))
.sort((a, b) => a.localeCompare(b))
.map((key) => {
const option: Completion = {
label: key + '()',
type: 'function',
};
const info = i18n.luxonStatic[key];
if (info) option.info = info;
return option;
return createLuxonAutocompleteOption(
key,
'native-function',
luxonStaticDocs,
i18n.luxonStatic,
);
});
};
const createLuxonAutocompleteOption = (
name: string,
type: AutocompleteOptionType,
docDefinition: NativeDoc,
translations: Record<string, string | undefined>,
): Completion => {
const option: Completion = {
label: isFunctionOption(type) ? name + '()' : name,
type,
};
let doc: DocMetadata | undefined;
if (docDefinition.properties && docDefinition.properties.hasOwnProperty(name)) {
doc = docDefinition.properties[name].doc;
} else if (docDefinition.functions.hasOwnProperty(name)) {
doc = docDefinition.functions[name].doc;
} else {
// Use inferred/default values if docs are still not updated
// This should happen when our doc specification becomes
// out-od-date with Luxon implementation
const optionType = typeof DateTime.prototype[name as keyof DateTime];
doc = {
name,
returnType: !optionType || optionType === 'undefined' ? '' : optionType,
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetime',
};
}
option.info = createCompletionOption('DateTime', name, type, {
// Add translated description
doc: { ...doc, description: translations[name] } as DocMetadata,
}).info;
return option;
};
/**
* Methods defined on the global `Object`.
*/

View File

@@ -0,0 +1,551 @@
import { NativeDoc } from 'n8n-workflow/src/Extensions/Extensions';
// Autocomplete documentation definition for DateTime instance props and methods
// Descriptions are added dynamically so they can be localized
export const luxonInstanceDocs: Required<NativeDoc> = {
typeName: 'DateTime',
properties: {
day: {
doc: {
name: 'day',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeday',
returnType: 'number',
},
},
daysInMonth: {
doc: {
name: 'daysInMonth',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimedaysinmonth',
returnType: 'number',
},
},
daysInYear: {
doc: {
name: 'daysInYear',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimedaysinyear',
returnType: 'number',
},
},
hour: {
doc: {
name: 'hour',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimehour',
returnType: 'number',
},
},
locale: {
doc: {
name: 'locale',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimelocale',
returnType: 'string',
},
},
millisecond: {
doc: {
name: 'millisecond',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemillisecond',
returnType: 'number',
},
},
minute: {
doc: {
name: 'minute',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeminute',
returnType: 'number',
},
},
month: {
doc: {
name: 'month',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonth',
returnType: 'number',
},
},
monthLong: {
doc: {
name: 'monthLong',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonthlong',
returnType: 'string',
},
},
monthShort: {
doc: {
name: 'monthShort',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemonthshort',
returnType: 'string',
},
},
numberingSystem: {
doc: {
name: 'numberingSystem',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimenumberingsystem',
returnType: 'string',
},
},
offset: {
doc: {
name: 'offset',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeoffset',
returnType: 'number',
},
},
offsetNameLong: {
doc: {
name: 'offsetNameLong',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeoffsetnamelong',
returnType: 'string',
},
},
offsetNameShort: {
doc: {
name: 'offsetNameShort',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeoffsetnameshort',
returnType: 'string',
},
},
ordinal: {
doc: {
name: 'ordinal',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeordinal',
returnType: 'string',
},
},
outputCalendar: {
doc: {
name: 'outputCalendar',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeoutputcalendar',
returnType: 'string',
},
},
quarter: {
doc: {
name: 'quarter',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimequarter',
returnType: 'number',
},
},
second: {
doc: {
name: 'second',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesecond',
returnType: 'number',
},
},
weekday: {
doc: {
name: 'weekday',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekday',
returnType: 'number',
},
},
weekdayLong: {
doc: {
name: 'weekdayLong',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekdaylong',
returnType: 'string',
},
},
weekdayShort: {
doc: {
name: 'weekdayShort',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekdayshort',
returnType: 'string',
},
},
weekNumber: {
doc: {
name: 'weekNumber',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweeknumber',
returnType: 'number',
},
},
weeksInWeekYear: {
doc: {
name: 'weeksInWeekYear',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweeksinweekyear',
returnType: 'number',
},
},
weekYear: {
doc: {
name: 'weekYear',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeweekyear',
returnType: 'number',
},
},
year: {
doc: {
name: 'year',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeyear',
returnType: 'number',
},
},
zone: {
doc: {
name: 'zone',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimezone',
returnType: 'Zone',
},
},
zoneName: {
doc: {
name: 'zoneName',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimezonename',
returnType: 'string',
},
},
isInDST: {
doc: {
name: 'isInDST',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisindst',
returnType: 'boolean',
},
},
isInLeapYear: {
doc: {
name: 'isInLeapYear',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisinleapyear',
returnType: 'boolean',
},
},
isOffsetFixed: {
doc: {
name: 'isOffsetFixed',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisoffsetfixed',
returnType: 'boolean',
},
},
isValid: {
doc: {
name: 'isValid',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisvalid',
returnType: 'boolean',
},
},
},
functions: {
diff: {
doc: {
name: 'diff',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimediff',
returnType: 'Duration',
args: [
{ name: 'other', type: 'DateTime' },
{ name: 'unit', type: 'string|string[]' },
{ name: 'opts', type: 'object' },
],
},
},
diffNow: {
doc: {
name: 'diffNow',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimediffnow',
returnType: 'Duration',
args: [
{ name: 'unit', type: 'string|string[]' },
{ name: 'opts', type: 'object' },
],
},
},
endOf: {
doc: {
name: 'endOf',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeendof',
returnType: 'DateTime',
args: [{ name: 'unit', type: 'string' }],
},
},
equals: {
doc: {
name: 'equals',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeequals',
returnType: 'boolean',
args: [{ name: 'other', type: 'DateTime' }],
},
},
hasSame: {
doc: {
name: 'hasSame',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimehassame',
returnType: 'boolean',
args: [
{ name: 'other', type: 'DateTime' },
{ name: 'unit', type: 'string' },
],
},
},
minus: {
doc: {
name: 'minus',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeminus',
returnType: 'DateTime',
args: [{ name: 'duration', type: 'Duration|object|number' }],
},
},
plus: {
doc: {
name: 'plus',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeplus',
returnType: 'DateTime',
args: [{ name: 'duration', type: 'Duration|object|number' }],
},
},
reconfigure: {
doc: {
name: 'reconfigure',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimereconfigure',
returnType: 'DateTime',
args: [{ name: 'properties', type: 'object' }],
},
},
resolvedLocaleOptions: {
doc: {
name: 'resolvedLocaleOptions',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeresolvedlocaleoptions',
returnType: 'object',
args: [{ name: 'opts', type: 'object' }],
},
},
set: {
doc: {
name: 'set',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeset',
returnType: 'DateTime',
args: [{ name: 'values', type: 'object' }],
},
},
setLocale: {
doc: {
name: 'setLocale',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesetlocale',
returnType: 'DateTime',
args: [{ name: 'locale', type: 'any' }],
},
},
setZone: {
doc: {
name: 'setZone',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimesetzone',
returnType: 'DateTime',
args: [
{ name: 'zone', type: 'string|Zone' },
{ name: 'opts', type: 'object' },
],
},
},
startOf: {
doc: {
name: 'startOf',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimestartof',
returnType: 'DateTime',
args: [{ name: 'unit', type: 'string' }],
},
},
toBSON: {
doc: {
name: 'toBSON',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetobson',
returnType: 'Date',
},
},
toFormat: {
doc: {
name: 'toFormat',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetime',
returnType: 'string',
args: [
{ name: 'fmt', type: 'string' },
{ name: 'opts', type: 'object' },
],
},
},
toHTTP: {
doc: {
name: 'toHTTP',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetohttp',
returnType: 'string',
},
},
toISO: {
doc: {
name: 'toISO',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoiso',
returnType: 'string',
args: [{ name: 'opts', type: 'object' }],
},
},
toISODate: {
doc: {
name: 'toISODate',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoisodate',
returnType: 'string',
args: [{ name: 'opts', type: 'object' }],
},
},
toISOTime: {
doc: {
name: 'toISOTime',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoisotime',
returnType: 'string',
args: [{ name: 'opts', type: 'object' }],
},
},
toISOWeekDate: {
doc: {
name: 'toISOWeekDate',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoisoweekdate',
returnType: 'string',
},
},
toJSDate: {
doc: {
name: 'toJSDate',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetojsdate',
returnType: 'Date',
},
},
toJSON: {
doc: {
name: 'toJSON',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetojson',
returnType: 'string',
},
},
toLocal: {
doc: {
name: 'toLocal',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetolocal',
returnType: 'DateTime',
},
},
toLocaleParts: {
doc: {
name: 'toLocaleParts',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetolocaleparts',
returnType: 'string',
args: [
{ name: 'formatOpts', type: 'any' },
{ name: 'opts', type: 'object' },
],
},
},
toLocaleString: {
doc: {
name: 'toLocaleString',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetolocalestring',
returnType: 'string',
args: [
{ name: 'formatOpts', type: 'any' },
{ name: 'opts', type: 'object' },
],
},
},
toMillis: {
doc: {
name: 'toMillis',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetomillis',
returnType: 'number',
},
},
toObject: {
doc: {
name: 'toObject',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoobject',
returnType: 'object',
args: [{ name: 'opts', type: 'any' }],
},
},
toRelative: {
doc: {
name: 'toRelative',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetorelative',
returnType: 'string',
args: [{ name: 'options', type: 'object' }],
},
},
toRelativeCalendar: {
doc: {
name: 'toRelativeCalendar',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetorelativecalendar',
returnType: 'string',
args: [{ name: 'options', type: 'object' }],
},
},
toRFC2822: {
doc: {
name: 'toRFC2822',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetorfc2822',
returnType: 'string',
},
},
toSeconds: {
doc: {
name: 'toSeconds',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoseconds',
returnType: 'number',
},
},
toSQL: {
doc: {
name: 'toSQL',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetosql',
returnType: 'string',
args: [{ name: 'options', type: 'object' }],
},
},
toSQLDate: {
doc: {
name: 'toSQLDate',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetosqldate',
returnType: 'string',
},
},
toSQLTime: {
doc: {
name: 'toSQLTime',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetosqltime',
returnType: 'string',
},
},
toString: {
doc: {
name: 'toString',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetostring',
returnType: 'string',
},
},
toUnixInteger: {
doc: {
name: 'toUnixInteger',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetounixinteger',
returnType: 'number',
},
},
toUTC: {
doc: {
name: 'toUTC',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimetoutc',
returnType: 'DateTime',
args: [
{ name: 'offset', type: 'number' },
{ name: 'opts', type: 'object' },
],
},
},
until: {
doc: {
name: 'until',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeuntil',
returnType: 'Interval',
args: [{ name: 'other', type: 'DateTime' }],
},
},
valueOf: {
doc: {
name: 'valueOf',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimevalueof',
returnType: 'number',
},
},
},
};

View File

@@ -0,0 +1,250 @@
import { NativeDoc } from 'n8n-workflow/src/Extensions/Extensions';
// Autocomplete documentation definition for DateTime class static props and methods
// Descriptions are added dynamically so they can be localized
export const luxonStaticDocs: Required<NativeDoc> = {
typeName: 'DateTime',
properties: {},
functions: {
now: {
doc: {
name: 'now',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimenow',
returnType: 'DateTime',
},
},
local: {
doc: {
name: 'local',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimelocal',
returnType: 'DateTime',
args: [
{ name: 'year?', type: 'number' },
{ name: 'month', type: 'number' },
{ name: 'day', type: 'number' },
{ name: 'hour', type: 'number' },
{ name: 'minute', type: 'number' },
{ name: 'second', type: 'number' },
{ name: 'millisecond', type: 'number' },
],
},
},
utc: {
doc: {
name: 'utc',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeutc',
returnType: 'DateTime',
args: [
{ name: 'year?', type: 'number' },
{ name: 'month', type: 'number' },
{ name: 'day', type: 'number' },
{ name: 'hour', type: 'number' },
{ name: 'minute', type: 'number' },
{ name: 'second', type: 'number' },
{ name: 'millisecond', type: 'number' },
],
},
},
fromJSDate: {
doc: {
name: 'fromJSDate',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromjsdate',
returnType: 'DateTime',
args: [
{ name: 'date', type: 'Date' },
{ name: 'options?', type: 'object' },
],
},
},
fromMillis: {
doc: {
name: 'fromMillis',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefrommillis',
returnType: 'DateTime',
args: [
{ name: 'milliseconds', type: 'number' },
{ name: 'options?', type: 'object' },
],
},
},
fromSeconds: {
doc: {
name: 'fromSeconds',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromseconds',
returnType: 'DateTime',
args: [
{ name: 'seconds', type: 'number' },
{ name: 'options?', type: 'object' },
],
},
},
fromObject: {
doc: {
name: 'fromObject',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromobject',
returnType: 'DateTime',
args: [
{ name: 'obj', type: 'object' },
{ name: 'options?', type: 'object' },
],
},
},
fromISO: {
doc: {
name: 'fromISO',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromiso',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromRFC2822: {
doc: {
name: 'fromRFC2822',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromrfc2822',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromHTTP: {
doc: {
name: 'fromHTTP',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromhttp',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromFormat: {
doc: {
name: 'fromFormat',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromformat',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'fmt', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromSQL: {
doc: {
name: 'fromSQL',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromsql',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
invalid: {
doc: {
name: 'invalid',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeinvalid',
returnType: 'DateTime',
args: [
{ name: 'reason', type: 'DateTime' },
{ name: 'explanation?', type: 'string' },
],
},
},
isDateTime: {
doc: {
name: 'isDateTime',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeisdatetime',
returnType: 'boolean',
args: [{ name: 'o', type: 'object' }],
},
},
expandFormat: {
doc: {
name: 'expandFormat',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeexpandformat',
returnType: 'string',
args: [
{ name: 'fmt', type: 'any' },
{ name: 'localeOpts?', type: 'any' },
],
},
},
fromFormatExplain: {
doc: {
name: 'fromFormatExplain',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromformatexplain',
returnType: 'object',
args: [
{ name: 'text', type: 'string' },
{ name: 'fmt', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromString: {
doc: {
name: 'fromString',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromstring',
returnType: 'DateTime',
args: [
{ name: 'text', type: 'string' },
{ name: 'fmt', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
fromStringExplain: {
doc: {
name: 'fromStringExplain',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimefromstringexplain',
returnType: 'object',
args: [
{ name: 'text', type: 'string' },
{ name: 'fmt', type: 'string' },
{ name: 'options?', type: 'object' },
],
},
},
max: {
doc: {
name: 'max',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemax',
returnType: 'DateTime|undefined',
args: [
{ name: 'dateTime1', type: 'DateTime' },
{ name: '...' },
{ name: 'dateTimeN', type: 'DateTime' },
],
},
},
min: {
doc: {
name: 'min',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimemin',
returnType: 'DateTime|undefined',
args: [
{ name: 'dateTime1', type: 'DateTime' },
{ name: '...' },
{ name: 'dateTimeN', type: 'DateTime' },
],
},
},
parseFormatForOpts: {
doc: {
name: 'parseFormatForOpts',
docURL: 'https://moment.github.io/luxon/api-docs/index.html#datetimeparseformatforopts',
returnType: 'string',
args: [
{ name: 'fmt', type: 'any' },
{ name: 'localeOpts?', type: 'any' },
],
},
},
},
};

View File

@@ -0,0 +1,5 @@
import { AutocompleteOptionType, FunctionOptionType } from './types';
export const isFunctionOption = (value: AutocompleteOptionType): value is FunctionOptionType => {
return value === 'native-function' || value === 'extension-function';
};

View File

@@ -6,3 +6,7 @@ export type Resolved = ReturnType<typeof resolveParameter>;
export type ExtensionTypeName = 'number' | 'string' | 'date' | 'array' | 'object';
export type FnToDoc = { [fnName: string]: { doc?: DocMetadata } };
export type FunctionOptionType = 'native-function' | 'extension-function';
export type KeywordOptionType = 'keyword';
export type AutocompleteOptionType = FunctionOptionType | KeywordOptionType;