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:
committed by
GitHub
parent
bb4db58819
commit
ae634407a4
@@ -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`.
|
||||
*/
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { AutocompleteOptionType, FunctionOptionType } from './types';
|
||||
|
||||
export const isFunctionOption = (value: AutocompleteOptionType): value is FunctionOptionType => {
|
||||
return value === 'native-function' || value === 'extension-function';
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user