mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
refactor(editor): Replace monaco-editor/prismjs with CodeMirror (#5983)
Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com> Co-authored-by: Milorad FIlipović <milorad@n8n.io> Co-authored-by: Alex Grozav <alex@grozav.com>
This commit is contained in:
parent
88724bb056
commit
ca4e0df90b
|
@ -18,7 +18,7 @@ export class NDV extends BasePage {
|
||||||
outputDisplayMode: () => this.getters.outputPanel().findChildByTestId('ndv-run-data-display-mode').first(),
|
outputDisplayMode: () => this.getters.outputPanel().findChildByTestId('ndv-run-data-display-mode').first(),
|
||||||
pinDataButton: () => cy.getByTestId('ndv-pin-data'),
|
pinDataButton: () => cy.getByTestId('ndv-pin-data'),
|
||||||
editPinnedDataButton: () => cy.getByTestId('ndv-edit-pinned-data'),
|
editPinnedDataButton: () => cy.getByTestId('ndv-edit-pinned-data'),
|
||||||
pinnedDataEditor: () => this.getters.outputPanel().find('.monaco-editor[role=code]'),
|
pinnedDataEditor: () => this.getters.outputPanel().find('.cm-editor .cm-scroller'),
|
||||||
runDataPaneHeader: () => cy.getByTestId('run-data-pane-header'),
|
runDataPaneHeader: () => cy.getByTestId('run-data-pane-header'),
|
||||||
savePinnedDataButton: () => this.getters.runDataPaneHeader().find('button').filter(':visible').contains('Save'),
|
savePinnedDataButton: () => this.getters.runDataPaneHeader().find('button').filter(':visible').contains('Save'),
|
||||||
outputTableRows: () => this.getters.outputDataContainer().find('table tr'),
|
outputTableRows: () => this.getters.outputDataContainer().find('table tr'),
|
||||||
|
@ -77,8 +77,7 @@ export class NDV extends BasePage {
|
||||||
this.getters.editPinnedDataButton().click();
|
this.getters.editPinnedDataButton().click();
|
||||||
|
|
||||||
this.getters.pinnedDataEditor().click();
|
this.getters.pinnedDataEditor().click();
|
||||||
this.getters.pinnedDataEditor().type(`{selectall}{backspace}`);
|
this.getters.pinnedDataEditor().type(`{selectall}{backspace}${JSON.stringify(data).replace(new RegExp('{', 'g'), '{{}')}`);
|
||||||
this.getters.pinnedDataEditor().type(JSON.stringify(data).replace(new RegExp('{', 'g'), '{{}'));
|
|
||||||
|
|
||||||
this.actions.savePinnedData();
|
this.actions.savePinnedData();
|
||||||
},
|
},
|
||||||
|
|
|
@ -276,6 +276,7 @@
|
||||||
--color-json-highlight: #dcdfea;
|
--color-json-highlight: #dcdfea;
|
||||||
|
|
||||||
--color-code-background: #222020;
|
--color-code-background: #222020;
|
||||||
|
--color-code-background-readonly: #323230;
|
||||||
--color-code-foreground: #f8f8f2;
|
--color-code-foreground: #f8f8f2;
|
||||||
--color-code-caret: #f8f8f0;
|
--color-code-caret: #f8f8f0;
|
||||||
--color-code-selection: #312b25;
|
--color-code-selection: #312b25;
|
||||||
|
|
|
@ -377,6 +377,7 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
--color-code-background: #ffffff;
|
--color-code-background: #ffffff;
|
||||||
|
--color-code-background-readonly: #f5f2f0;
|
||||||
--color-code-foreground: #4d4d4c;
|
--color-code-foreground: #4d4d4c;
|
||||||
--color-code-caret: #aeafad;
|
--color-code-caret: #aeafad;
|
||||||
--color-code-selection: #d6d6d6;
|
--color-code-selection: #d6d6d6;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
"@codemirror/autocomplete": "^6.4.0",
|
"@codemirror/autocomplete": "^6.4.0",
|
||||||
"@codemirror/commands": "^6.1.0",
|
"@codemirror/commands": "^6.1.0",
|
||||||
"@codemirror/lang-javascript": "^6.1.2",
|
"@codemirror/lang-javascript": "^6.1.2",
|
||||||
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/language": "^6.2.1",
|
"@codemirror/language": "^6.2.1",
|
||||||
"@codemirror/lint": "^6.0.0",
|
"@codemirror/lint": "^6.0.0",
|
||||||
"@codemirror/state": "^6.1.4",
|
"@codemirror/state": "^6.1.4",
|
||||||
|
@ -58,13 +59,11 @@
|
||||||
"jsonpath": "^1.1.1",
|
"jsonpath": "^1.1.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"monaco-editor": "^0.33.0",
|
|
||||||
"n8n-design-system": "workspace:*",
|
"n8n-design-system": "workspace:*",
|
||||||
"n8n-workflow": "workspace:*",
|
"n8n-workflow": "workspace:*",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
"pinia": "^2.0.22",
|
"pinia": "^2.0.22",
|
||||||
"prettier": "^2.8.3",
|
"prettier": "^2.8.3",
|
||||||
"prismjs": "^1.17.1",
|
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"timeago.js": "^4.0.2",
|
"timeago.js": "^4.0.2",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
|
@ -75,7 +74,6 @@
|
||||||
"vue-i18n": "^8.26.7",
|
"vue-i18n": "^8.26.7",
|
||||||
"vue-infinite-loading": "^2.4.5",
|
"vue-infinite-loading": "^2.4.5",
|
||||||
"vue-json-pretty": "1.9.3",
|
"vue-json-pretty": "1.9.3",
|
||||||
"vue-prism-editor": "^0.3.0",
|
|
||||||
"vue-router": "^3.6.5",
|
"vue-router": "^3.6.5",
|
||||||
"vue-template-compiler": "^2.7.14",
|
"vue-template-compiler": "^2.7.14",
|
||||||
"vue-typed-mixins": "^0.2.0",
|
"vue-typed-mixins": "^0.2.0",
|
||||||
|
@ -113,7 +111,6 @@
|
||||||
"sass-loader": "^10.1.1",
|
"sass-loader": "^10.1.1",
|
||||||
"string-template-parser": "^1.2.6",
|
"string-template-parser": "^1.2.6",
|
||||||
"vite": "4.0.4",
|
"vite": "4.0.4",
|
||||||
"vite-plugin-monaco-editor": "^1.0.10",
|
|
||||||
"vitest": "^0.28.5",
|
"vitest": "^0.28.5",
|
||||||
"vue-tsc": "^1.0.24"
|
"vue-tsc": "^1.0.24"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,281 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
visible
|
|
||||||
append-to-body
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
width="80%"
|
|
||||||
:title="`${$locale.baseText('codeEdit.edit')} ${$locale
|
|
||||||
.nodeText()
|
|
||||||
.inputLabelDisplayName(parameter, path)}`"
|
|
||||||
:before-close="closeDialog"
|
|
||||||
>
|
|
||||||
<div class="text-editor-wrapper ignore-key-press">
|
|
||||||
<code-editor
|
|
||||||
:value="value"
|
|
||||||
:autocomplete="loadAutocompleteData"
|
|
||||||
:readonly="readonly"
|
|
||||||
@input="$emit('valueChanged', $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { workflowHelpers } from '@/mixins/workflowHelpers';
|
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
|
||||||
import type { INodeUi } from '@/Interface';
|
|
||||||
import type {
|
|
||||||
IBinaryKeyData,
|
|
||||||
IDataObject,
|
|
||||||
INodeExecutionData,
|
|
||||||
IRunExecutionData,
|
|
||||||
IWorkflowDataProxyAdditionalKeys,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
import { WorkflowDataProxy } from 'n8n-workflow';
|
|
||||||
|
|
||||||
import { PLACEHOLDER_FILLED_AT_EXECUTION_TIME } from '@/constants';
|
|
||||||
import { CodeEditor } from './forms';
|
|
||||||
import { mapStores } from 'pinia';
|
|
||||||
import { useWorkflowsStore } from '@/stores/workflows';
|
|
||||||
import { useRootStore } from '@/stores/n8nRootStore';
|
|
||||||
import { useNDVStore } from '@/stores/ndv';
|
|
||||||
|
|
||||||
export default mixins(genericHelpers, workflowHelpers).extend({
|
|
||||||
name: 'CodeEdit',
|
|
||||||
components: {
|
|
||||||
CodeEditor,
|
|
||||||
},
|
|
||||||
props: ['codeAutocomplete', 'parameter', 'path', 'type', 'value', 'readonly'],
|
|
||||||
computed: {
|
|
||||||
...mapStores(useNDVStore, useRootStore, useWorkflowsStore),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
loadAutocompleteData(): string[] {
|
|
||||||
if (['function', 'functionItem'].includes(this.codeAutocomplete)) {
|
|
||||||
const itemIndex = 0;
|
|
||||||
const inputName = 'main';
|
|
||||||
const mode = 'manual';
|
|
||||||
let runIndex = 0;
|
|
||||||
|
|
||||||
const executedWorkflow = this.workflowsStore.getWorkflowExecution;
|
|
||||||
const workflow = this.getCurrentWorkflow();
|
|
||||||
const activeNode: INodeUi | null = this.ndvStore.activeNode;
|
|
||||||
const parentNode = workflow.getParentNodes(activeNode!.name, inputName, 1);
|
|
||||||
const nodeConnection = workflow.getNodeConnectionIndexes(
|
|
||||||
activeNode!.name,
|
|
||||||
parentNode[0],
|
|
||||||
) || {
|
|
||||||
sourceIndex: 0,
|
|
||||||
destinationIndex: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const executionData = this.workflowsStore.getWorkflowExecution;
|
|
||||||
|
|
||||||
let runExecutionData: IRunExecutionData;
|
|
||||||
if (!executionData || !executionData.data) {
|
|
||||||
runExecutionData = {
|
|
||||||
resultData: {
|
|
||||||
runData: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
runExecutionData = executionData.data;
|
|
||||||
if (runExecutionData.resultData.runData[activeNode!.name]) {
|
|
||||||
runIndex = runExecutionData.resultData.runData[activeNode!.name].length - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const connectionInputData = this.connectionInputData(
|
|
||||||
parentNode,
|
|
||||||
activeNode!.name,
|
|
||||||
inputName,
|
|
||||||
runIndex,
|
|
||||||
nodeConnection,
|
|
||||||
);
|
|
||||||
|
|
||||||
const additionalProxyKeys: IWorkflowDataProxyAdditionalKeys = {
|
|
||||||
$execution: {
|
|
||||||
id: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
mode: 'test',
|
|
||||||
resumeUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
},
|
|
||||||
|
|
||||||
// deprecated
|
|
||||||
$executionId: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataProxy = new WorkflowDataProxy(
|
|
||||||
workflow,
|
|
||||||
runExecutionData,
|
|
||||||
runIndex,
|
|
||||||
itemIndex,
|
|
||||||
activeNode!.name,
|
|
||||||
connectionInputData || [],
|
|
||||||
{},
|
|
||||||
mode,
|
|
||||||
this.rootStore.timezone,
|
|
||||||
additionalProxyKeys,
|
|
||||||
);
|
|
||||||
const proxy = dataProxy.getDataProxy();
|
|
||||||
|
|
||||||
const autoCompleteItems = [
|
|
||||||
'function $evaluateExpression(expression: string, itemIndex?: number): any {};',
|
|
||||||
'function getNodeParameter(parameterName: string, itemIndex: number, fallbackValue?: any): any {};',
|
|
||||||
'function getWorkflowStaticData(type: string): {};',
|
|
||||||
'function $item(itemIndex: number, runIndex?: number): {};',
|
|
||||||
'function $items(nodeName?: string, outputIndex?: number, runIndex?: number): {};',
|
|
||||||
];
|
|
||||||
|
|
||||||
const baseKeys = [
|
|
||||||
'$env',
|
|
||||||
'$executionId',
|
|
||||||
'$mode',
|
|
||||||
'$parameter',
|
|
||||||
'$resumeWebhookUrl',
|
|
||||||
'$vars',
|
|
||||||
'$workflow',
|
|
||||||
'$now',
|
|
||||||
'$today',
|
|
||||||
'$thisRunIndex',
|
|
||||||
'DateTime',
|
|
||||||
'Duration',
|
|
||||||
'Interval',
|
|
||||||
];
|
|
||||||
|
|
||||||
const functionItemKeys = ['$json', '$binary', '$position', '$thisItem', '$thisItemIndex'];
|
|
||||||
|
|
||||||
const additionalKeys: string[] = [];
|
|
||||||
if (this.codeAutocomplete === 'functionItem') {
|
|
||||||
additionalKeys.push(...functionItemKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executedWorkflow && connectionInputData && connectionInputData.length) {
|
|
||||||
baseKeys.push(...additionalKeys);
|
|
||||||
} else {
|
|
||||||
additionalKeys.forEach((key) => {
|
|
||||||
autoCompleteItems.push(`const ${key} = {}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of baseKeys) {
|
|
||||||
autoCompleteItems.push(
|
|
||||||
`const ${key} = ${JSON.stringify(this.createSimpleRepresentation(proxy[key]))}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the nodes and their simplified data
|
|
||||||
const nodes: {
|
|
||||||
[key: string]: INodeExecutionData;
|
|
||||||
} = {};
|
|
||||||
for (const [nodeName, node] of Object.entries(workflow.nodes)) {
|
|
||||||
// To not load to much data create a simple representation.
|
|
||||||
nodes[nodeName] = {
|
|
||||||
json: {} as IDataObject,
|
|
||||||
parameter: this.createSimpleRepresentation(
|
|
||||||
proxy.$node[nodeName].parameter,
|
|
||||||
) as IDataObject,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
nodes[nodeName]!.json = this.createSimpleRepresentation(
|
|
||||||
proxy.$node[nodeName].json,
|
|
||||||
) as IDataObject;
|
|
||||||
nodes[nodeName]!.context = this.createSimpleRepresentation(
|
|
||||||
proxy.$node[nodeName].context,
|
|
||||||
) as IDataObject;
|
|
||||||
nodes[nodeName]!.runIndex = proxy.$node[nodeName].runIndex;
|
|
||||||
if (Object.keys(proxy.$node[nodeName].binary).length) {
|
|
||||||
nodes[nodeName]!.binary = this.createSimpleRepresentation(
|
|
||||||
proxy.$node[nodeName].binary,
|
|
||||||
) as IBinaryKeyData;
|
|
||||||
}
|
|
||||||
} catch (error) {}
|
|
||||||
}
|
|
||||||
autoCompleteItems.push(`const $node = ${JSON.stringify(nodes)}`);
|
|
||||||
autoCompleteItems.push('function $jmespath(jsonDoc: object, query: string): {};');
|
|
||||||
|
|
||||||
if (this.codeAutocomplete === 'function') {
|
|
||||||
if (connectionInputData) {
|
|
||||||
autoCompleteItems.push(
|
|
||||||
`const items = ${JSON.stringify(
|
|
||||||
this.createSimpleRepresentation(connectionInputData),
|
|
||||||
)}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
autoCompleteItems.push('const items: {json: {[key: string]: any}}[] = []');
|
|
||||||
}
|
|
||||||
} else if (this.codeAutocomplete === 'functionItem') {
|
|
||||||
if (connectionInputData) {
|
|
||||||
autoCompleteItems.push('const item = $json');
|
|
||||||
} else {
|
|
||||||
autoCompleteItems.push('const item: {[key: string]: any} = {}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return autoCompleteItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
closeDialog() {
|
|
||||||
// Handle the close externally as the visible parameter is an external prop
|
|
||||||
// and is so not allowed to be changed here.
|
|
||||||
this.$emit('closeDialog');
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
createSimpleRepresentation(
|
|
||||||
inputData:
|
|
||||||
| object
|
|
||||||
| null
|
|
||||||
| undefined
|
|
||||||
| boolean
|
|
||||||
| string
|
|
||||||
| number
|
|
||||||
| boolean[]
|
|
||||||
| string[]
|
|
||||||
| number[]
|
|
||||||
| object[],
|
|
||||||
):
|
|
||||||
| object
|
|
||||||
| null
|
|
||||||
| undefined
|
|
||||||
| boolean
|
|
||||||
| string
|
|
||||||
| number
|
|
||||||
| boolean[]
|
|
||||||
| string[]
|
|
||||||
| number[]
|
|
||||||
| object[] {
|
|
||||||
if (inputData === null || inputData === undefined) {
|
|
||||||
return inputData;
|
|
||||||
} else if (typeof inputData === 'string') {
|
|
||||||
return '';
|
|
||||||
} else if (typeof inputData === 'boolean') {
|
|
||||||
return true;
|
|
||||||
} else if (typeof inputData === 'number') {
|
|
||||||
return 1;
|
|
||||||
} else if (Array.isArray(inputData)) {
|
|
||||||
return inputData.map((value) => this.createSimpleRepresentation(value));
|
|
||||||
} else if (typeof inputData === 'object') {
|
|
||||||
const returnData: { [key: string]: object } = {};
|
|
||||||
Object.keys(inputData).forEach((key) => {
|
|
||||||
// @ts-ignore
|
|
||||||
returnData[key] = this.createSimpleRepresentation(inputData[key]);
|
|
||||||
});
|
|
||||||
return returnData;
|
|
||||||
}
|
|
||||||
return inputData;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.text-editor {
|
|
||||||
min-height: 30rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="$style['code-node-editor-container']"
|
:class="['code-node-editor', $style['code-node-editor-container']]"
|
||||||
@mouseover="onMouseOver"
|
@mouseover="onMouseOver"
|
||||||
@mouseout="onMouseOut"
|
@mouseout="onMouseOut"
|
||||||
ref="codeNodeEditorContainer"
|
ref="codeNodeEditorContainer"
|
||||||
>
|
>
|
||||||
<div ref="codeNodeEditor" class="ph-no-capture"></div>
|
<div ref="codeNodeEditor" class="code-node-editor-input ph-no-capture"></div>
|
||||||
<n8n-button
|
<n8n-button
|
||||||
v-if="isCloud && (isEditorHovered || isEditorFocused)"
|
v-if="isCloud && (isEditorHovered || isEditorFocused)"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -19,40 +19,60 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
|
import type { Extension } from '@codemirror/state';
|
||||||
import { Compartment, EditorState } from '@codemirror/state';
|
import { Compartment, EditorState } from '@codemirror/state';
|
||||||
import type { ViewUpdate } from '@codemirror/view';
|
import type { ViewUpdate } from '@codemirror/view';
|
||||||
import { EditorView } from '@codemirror/view';
|
import { EditorView } from '@codemirror/view';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
|
import { json } from '@codemirror/lang-json';
|
||||||
|
|
||||||
import { baseExtensions } from './baseExtensions';
|
import { readOnlyEditorExtensions, writableEditorExtensions } from './baseExtensions';
|
||||||
import { linterExtension } from './linter';
|
import { linterExtension } from './linter';
|
||||||
import { completerExtension } from './completer';
|
import { completerExtension } from './completer';
|
||||||
import { CODE_NODE_EDITOR_THEME } from './theme';
|
import { codeNodeEditorTheme } from './theme';
|
||||||
import { workflowHelpers } from '@/mixins/workflowHelpers'; // for json field completions
|
import { workflowHelpers } from '@/mixins/workflowHelpers'; // for json field completions
|
||||||
import { ASK_AI_MODAL_KEY, CODE_NODE_TYPE } from '@/constants';
|
import { ASK_AI_MODAL_KEY, CODE_NODE_TYPE } from '@/constants';
|
||||||
import { codeNodeEditorEventBus } from '@/event-bus';
|
import { codeNodeEditorEventBus } from '@/event-bus';
|
||||||
import { ALL_ITEMS_PLACEHOLDER, EACH_ITEM_PLACEHOLDER } from './constants';
|
import {
|
||||||
import { mapStores } from 'pinia';
|
ALL_ITEMS_PLACEHOLDER,
|
||||||
|
CODE_LANGUAGES,
|
||||||
|
CODE_MODES,
|
||||||
|
EACH_ITEM_PLACEHOLDER,
|
||||||
|
} from './constants';
|
||||||
import { useRootStore } from '@/stores/n8nRootStore';
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
import Modal from '../Modal.vue';
|
import Modal from '../Modal.vue';
|
||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import type { CodeLanguage, CodeMode } from './types';
|
||||||
|
|
||||||
|
const placeholders: Partial<Record<CodeLanguage, Record<CodeMode, string>>> = {
|
||||||
|
javaScript: {
|
||||||
|
runOnceForAllItems: ALL_ITEMS_PLACEHOLDER,
|
||||||
|
runOnceForEachItem: EACH_ITEM_PLACEHOLDER,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default mixins(linterExtension, completerExtension, workflowHelpers).extend({
|
export default mixins(linterExtension, completerExtension, workflowHelpers).extend({
|
||||||
name: 'code-node-editor',
|
name: 'code-node-editor',
|
||||||
components: { Modal },
|
components: { Modal },
|
||||||
props: {
|
props: {
|
||||||
mode: {
|
mode: {
|
||||||
type: String,
|
type: String as PropType<CodeMode>,
|
||||||
validator: (value: string): boolean =>
|
validator: (value: CodeMode): boolean => CODE_MODES.includes(value),
|
||||||
['runOnceForAllItems', 'runOnceForEachItem'].includes(value),
|
},
|
||||||
|
language: {
|
||||||
|
type: String as PropType<CodeLanguage>,
|
||||||
|
default: 'javaScript' as CodeLanguage,
|
||||||
|
validator: (value: CodeLanguage): boolean => CODE_LANGUAGES.includes(value),
|
||||||
},
|
},
|
||||||
isReadOnly: {
|
isReadOnly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
jsCode: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -65,9 +85,12 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
mode() {
|
mode(newMode, previousMode: CodeMode) {
|
||||||
this.reloadLinter();
|
this.reloadLinter();
|
||||||
this.refreshPlaceholder();
|
|
||||||
|
if (this.content.trim() === placeholders[this.language]?.[previousMode]) {
|
||||||
|
this.refreshPlaceholder();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -81,16 +104,7 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
return this.editor.state.doc.toString();
|
return this.editor.state.doc.toString();
|
||||||
},
|
},
|
||||||
placeholder(): string {
|
placeholder(): string {
|
||||||
return {
|
return placeholders[this.language]?.[this.mode] ?? '';
|
||||||
runOnceForAllItems: ALL_ITEMS_PLACEHOLDER,
|
|
||||||
runOnceForEachItem: EACH_ITEM_PLACEHOLDER,
|
|
||||||
}[this.mode];
|
|
||||||
},
|
|
||||||
previousPlaceholder(): string {
|
|
||||||
return {
|
|
||||||
runOnceForAllItems: EACH_ITEM_PLACEHOLDER,
|
|
||||||
runOnceForEachItem: ALL_ITEMS_PLACEHOLDER,
|
|
||||||
}[this.mode];
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -114,25 +128,26 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
reloadLinter() {
|
reloadLinter() {
|
||||||
if (!this.editor) return;
|
if (!this.editor) return;
|
||||||
|
|
||||||
this.editor.dispatch({
|
const linter = this.createLinter(this.language);
|
||||||
effects: this.linterCompartment.reconfigure(this.linterExtension()),
|
if (linter) {
|
||||||
});
|
this.editor.dispatch({
|
||||||
|
effects: this.linterCompartment.reconfigure(linter),
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
refreshPlaceholder() {
|
refreshPlaceholder() {
|
||||||
if (!this.editor) return;
|
if (!this.editor) return;
|
||||||
|
|
||||||
if (!this.content.trim() || this.content.trim() === this.previousPlaceholder) {
|
this.editor.dispatch({
|
||||||
this.editor.dispatch({
|
changes: { from: 0, to: this.content.length, insert: this.placeholder },
|
||||||
changes: { from: 0, to: this.content.length, insert: this.placeholder },
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
highlightLine(line: number | 'final') {
|
highlightLine(line: number | 'final') {
|
||||||
if (!this.editor) return;
|
if (!this.editor) return;
|
||||||
|
|
||||||
if (line === 'final') {
|
if (line === 'final') {
|
||||||
this.editor.dispatch({
|
this.editor.dispatch({
|
||||||
selection: { anchor: this.content.trim().length },
|
selection: { anchor: this.content.length },
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -175,45 +190,62 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
codeNodeEditorEventBus.off('error-line-number', this.highlightLine);
|
if (!this.isReadOnly) codeNodeEditorEventBus.off('error-line-number', this.highlightLine);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
codeNodeEditorEventBus.on('error-line-number', this.highlightLine);
|
if (!this.isReadOnly) codeNodeEditorEventBus.on('error-line-number', this.highlightLine);
|
||||||
|
|
||||||
const stateBasedExtensions = [
|
|
||||||
this.linterCompartment.of(this.linterExtension()),
|
|
||||||
EditorState.readOnly.of(this.isReadOnly),
|
|
||||||
EditorView.domEventHandlers({
|
|
||||||
focus: () => {
|
|
||||||
this.isEditorFocused = true;
|
|
||||||
},
|
|
||||||
blur: () => {
|
|
||||||
this.isEditorFocused = false;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
EditorView.updateListener.of((viewUpdate: ViewUpdate) => {
|
|
||||||
if (!viewUpdate.docChanged) return;
|
|
||||||
|
|
||||||
this.trackCompletion(viewUpdate);
|
|
||||||
|
|
||||||
this.$emit('valueChanged', this.content);
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
// empty on first load, default param value
|
// empty on first load, default param value
|
||||||
if (this.jsCode === '') {
|
if (!this.value) {
|
||||||
this.$emit('valueChanged', this.placeholder);
|
this.$emit('valueChanged', this.placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { isReadOnly, language } = this;
|
||||||
|
const extensions: Extension[] = [
|
||||||
|
...readOnlyEditorExtensions,
|
||||||
|
EditorState.readOnly.of(isReadOnly),
|
||||||
|
EditorView.editable.of(!isReadOnly),
|
||||||
|
codeNodeEditorTheme({ isReadOnly }),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isReadOnly) {
|
||||||
|
const linter = this.createLinter(language);
|
||||||
|
if (linter) {
|
||||||
|
extensions.push(this.linterCompartment.of(linter));
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.push(
|
||||||
|
...writableEditorExtensions,
|
||||||
|
EditorView.domEventHandlers({
|
||||||
|
focus: () => {
|
||||||
|
this.isEditorFocused = true;
|
||||||
|
},
|
||||||
|
blur: () => {
|
||||||
|
this.isEditorFocused = false;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
EditorView.updateListener.of((viewUpdate) => {
|
||||||
|
if (!viewUpdate.docChanged) return;
|
||||||
|
|
||||||
|
this.trackCompletion(viewUpdate);
|
||||||
|
|
||||||
|
this.$emit('valueChanged', this.editor?.state.doc.toString());
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (language) {
|
||||||
|
case 'json':
|
||||||
|
extensions.push(json());
|
||||||
|
break;
|
||||||
|
case 'javaScript':
|
||||||
|
extensions.push(javascript(), this.autocompletionExtension());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const state = EditorState.create({
|
const state = EditorState.create({
|
||||||
doc: this.jsCode === '' ? this.placeholder : this.jsCode,
|
doc: this.value || this.placeholder,
|
||||||
extensions: [
|
extensions,
|
||||||
...baseExtensions,
|
|
||||||
...stateBasedExtensions,
|
|
||||||
CODE_NODE_EDITOR_THEME,
|
|
||||||
javascript(),
|
|
||||||
this.autocompletionExtension(),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.editor = new EditorView({
|
this.editor = new EditorView({
|
||||||
|
@ -227,6 +259,10 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.code-node-editor-container {
|
.code-node-editor-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ask-ai-button {
|
.ask-ai-button {
|
||||||
|
|
|
@ -18,21 +18,26 @@ import {
|
||||||
deleteCharBackward,
|
deleteCharBackward,
|
||||||
} from '@codemirror/commands';
|
} from '@codemirror/commands';
|
||||||
import { lintGutter } from '@codemirror/lint';
|
import { lintGutter } from '@codemirror/lint';
|
||||||
|
import type { Extension } from '@codemirror/state';
|
||||||
|
|
||||||
import { codeInputHandler } from '@/plugins/codemirror/inputHandlers/code.inputHandler';
|
import { codeInputHandler } from '@/plugins/codemirror/inputHandlers/code.inputHandler';
|
||||||
|
|
||||||
export const baseExtensions = [
|
export const readOnlyEditorExtensions: readonly Extension[] = [
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
highlightActiveLineGutter(),
|
EditorView.lineWrapping,
|
||||||
highlightSpecialChars(),
|
highlightSpecialChars(),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const writableEditorExtensions: readonly Extension[] = [
|
||||||
history(),
|
history(),
|
||||||
foldGutter(),
|
|
||||||
lintGutter(),
|
lintGutter(),
|
||||||
|
foldGutter(),
|
||||||
codeInputHandler(),
|
codeInputHandler(),
|
||||||
dropCursor(),
|
dropCursor(),
|
||||||
indentOnInput(),
|
indentOnInput(),
|
||||||
bracketMatching(),
|
bracketMatching(),
|
||||||
highlightActiveLine(),
|
highlightActiveLine(),
|
||||||
|
highlightActiveLineGutter(),
|
||||||
keymap.of([
|
keymap.of([
|
||||||
{ key: 'Enter', run: insertNewlineAndIndent },
|
{ key: 'Enter', run: insertNewlineAndIndent },
|
||||||
{ key: 'Tab', run: acceptCompletion },
|
{ key: 'Tab', run: acceptCompletion },
|
||||||
|
@ -42,5 +47,4 @@ export const baseExtensions = [
|
||||||
{ key: 'Backspace', run: deleteCharBackward, shift: deleteCharBackward },
|
{ key: 'Backspace', run: deleteCharBackward, shift: deleteCharBackward },
|
||||||
indentWithTab,
|
indentWithTab,
|
||||||
]),
|
]),
|
||||||
EditorView.lineWrapping,
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -51,3 +51,6 @@ $input.item.json.myNewField = 1;
|
||||||
|
|
||||||
return $input.item;
|
return $input.item;
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
|
export const CODE_LANGUAGES = ['javaScript', 'json'] as const;
|
||||||
|
export const CODE_MODES = ['runOnceForAllItems', 'runOnceForEachItem'] as const;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import type { Diagnostic } from '@codemirror/lint';
|
import type { Diagnostic } from '@codemirror/lint';
|
||||||
import { linter as createLinter } from '@codemirror/lint';
|
import { linter as createLinter } from '@codemirror/lint';
|
||||||
|
import { jsonParseLinter } from '@codemirror/lang-json';
|
||||||
import * as esprima from 'esprima-next';
|
import * as esprima from 'esprima-next';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -12,12 +13,18 @@ import { walk } from './utils';
|
||||||
|
|
||||||
import type { EditorView } from '@codemirror/view';
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { Node } from 'estree';
|
import type { Node } from 'estree';
|
||||||
import type { CodeNodeEditorMixin, RangeNode } from './types';
|
import type { CodeLanguage, CodeNodeEditorMixin, RangeNode } from './types';
|
||||||
|
|
||||||
export const linterExtension = (Vue as CodeNodeEditorMixin).extend({
|
export const linterExtension = (Vue as CodeNodeEditorMixin).extend({
|
||||||
methods: {
|
methods: {
|
||||||
linterExtension() {
|
createLinter(language: CodeLanguage) {
|
||||||
return createLinter(this.lintSource, { delay: DEFAULT_LINTER_DELAY_IN_MS });
|
switch (language) {
|
||||||
|
case 'javaScript':
|
||||||
|
return createLinter(this.lintSource, { delay: DEFAULT_LINTER_DELAY_IN_MS });
|
||||||
|
case 'json':
|
||||||
|
return createLinter(jsonParseLinter());
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
lintSource(editorView: EditorView): Diagnostic[] {
|
lintSource(editorView: EditorView): Diagnostic[] {
|
||||||
|
|
|
@ -29,7 +29,11 @@ const BASE_STYLING = {
|
||||||
|
|
||||||
const cssStyleDeclaration = getComputedStyle(document.documentElement);
|
const cssStyleDeclaration = getComputedStyle(document.documentElement);
|
||||||
|
|
||||||
export const CODE_NODE_EDITOR_THEME = [
|
interface ThemeSettings {
|
||||||
|
isReadOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const codeNodeEditorTheme = ({ isReadOnly }: ThemeSettings) => [
|
||||||
EditorView.theme({
|
EditorView.theme({
|
||||||
'&': {
|
'&': {
|
||||||
'font-size': BASE_STYLING.fontSize,
|
'font-size': BASE_STYLING.fontSize,
|
||||||
|
@ -37,6 +41,7 @@ export const CODE_NODE_EDITOR_THEME = [
|
||||||
borderRadius: cssStyleDeclaration.getPropertyValue('--border-radius-base'),
|
borderRadius: cssStyleDeclaration.getPropertyValue('--border-radius-base'),
|
||||||
backgroundColor: 'var(--color-code-background)',
|
backgroundColor: 'var(--color-code-background)',
|
||||||
color: 'var(--color-code-foreground)',
|
color: 'var(--color-code-foreground)',
|
||||||
|
height: '100%',
|
||||||
},
|
},
|
||||||
'.cm-content': {
|
'.cm-content': {
|
||||||
fontFamily: BASE_STYLING.fontFamily,
|
fontFamily: BASE_STYLING.fontFamily,
|
||||||
|
@ -48,6 +53,9 @@ export const CODE_NODE_EDITOR_THEME = [
|
||||||
'&.cm-focused .cm-selectionBackgroundm .cm-selectionBackground, .cm-content ::selection': {
|
'&.cm-focused .cm-selectionBackgroundm .cm-selectionBackground, .cm-content ::selection': {
|
||||||
backgroundColor: 'var(--color-code-selection)',
|
backgroundColor: 'var(--color-code-selection)',
|
||||||
},
|
},
|
||||||
|
'&.cm-editor': {
|
||||||
|
...(isReadOnly ? { backgroundColor: 'var(--color-code-background-readonly)' } : {}),
|
||||||
|
},
|
||||||
'&.cm-editor.cm-focused': {
|
'&.cm-editor.cm-focused': {
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
borderColor: 'var(--color-secondary)',
|
borderColor: 'var(--color-secondary)',
|
||||||
|
@ -59,7 +67,9 @@ export const CODE_NODE_EDITOR_THEME = [
|
||||||
backgroundColor: 'var(--color-code-lineHighlight)',
|
backgroundColor: 'var(--color-code-lineHighlight)',
|
||||||
},
|
},
|
||||||
'.cm-gutters': {
|
'.cm-gutters': {
|
||||||
backgroundColor: 'var(--color-code-gutterBackground)',
|
backgroundColor: isReadOnly
|
||||||
|
? 'var(--color-code-background-readonly)'
|
||||||
|
: 'var(--color-code-gutterBackground)',
|
||||||
color: 'var(--color-code-gutterForeground)',
|
color: 'var(--color-code-gutterForeground)',
|
||||||
borderRadius: 'var(--border-radius-base)',
|
borderRadius: 'var(--border-radius-base)',
|
||||||
},
|
},
|
||||||
|
@ -69,7 +79,8 @@ export const CODE_NODE_EDITOR_THEME = [
|
||||||
},
|
},
|
||||||
'.cm-scroller': {
|
'.cm-scroller': {
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
maxHeight: BASE_STYLING.maxHeight,
|
maxHeight: '100%',
|
||||||
|
...(isReadOnly ? {} : { minHeight: '10em' }),
|
||||||
},
|
},
|
||||||
'.cm-diagnosticAction': {
|
'.cm-diagnosticAction': {
|
||||||
backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor,
|
backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import type { EditorView } from '@codemirror/view';
|
||||||
import type { I18nClass } from '@/plugins/i18n';
|
import type { I18nClass } from '@/plugins/i18n';
|
||||||
import type { Workflow } from 'n8n-workflow';
|
import type { Workflow } from 'n8n-workflow';
|
||||||
import type { Node } from 'estree';
|
import type { Node } from 'estree';
|
||||||
|
import type { CODE_LANGUAGES, CODE_MODES } from './constants';
|
||||||
|
|
||||||
export type CodeNodeEditorMixin = Vue.VueConstructor<
|
export type CodeNodeEditorMixin = Vue.VueConstructor<
|
||||||
Vue & {
|
Vue & {
|
||||||
|
@ -13,3 +14,6 @@ export type CodeNodeEditorMixin = Vue.VueConstructor<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type RangeNode = Node & { range: [number, number] };
|
export type RangeNode = Node & { range: [number, number] };
|
||||||
|
|
||||||
|
export type CodeLanguage = (typeof CODE_LANGUAGES)[number];
|
||||||
|
export type CodeMode = (typeof CODE_MODES)[number];
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
}}</n8n-text>
|
}}</n8n-text>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #recovered-artifical-output-data>
|
<template #recovered-artificial-output-data>
|
||||||
<div :class="$style.recoveredOutputData">
|
<div :class="$style.recoveredOutputData">
|
||||||
<n8n-text tag="div" :bold="true" color="text-dark" size="large">{{
|
<n8n-text tag="div" :bold="true" color="text-dark" size="large">{{
|
||||||
$locale.baseText('executionDetails.executionFailed.recoveredNodeTitle')
|
$locale.baseText('executionDetails.executionFailed.recoveredNodeTitle')
|
||||||
|
|
|
@ -436,6 +436,10 @@ export default mixins(debounceHelper).extend({
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.double-width {
|
||||||
|
left: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
.dragButtonContainer {
|
.dragButtonContainer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -12px;
|
top: -12px;
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
:hideInputAndOutput="activeNodeType === null"
|
:hideInputAndOutput="activeNodeType === null"
|
||||||
:position="isTriggerNode && !showTriggerPanel ? 0 : undefined"
|
:position="isTriggerNode && !showTriggerPanel ? 0 : undefined"
|
||||||
:isDraggable="!isTriggerNode"
|
:isDraggable="!isTriggerNode"
|
||||||
|
:hasDoubleWidth="activeNodeType?.parameterPane === 'wide'"
|
||||||
:nodeType="activeNodeType"
|
:nodeType="activeNodeType"
|
||||||
@close="close"
|
@close="close"
|
||||||
@init="onPanelsInit"
|
@init="onPanelsInit"
|
||||||
|
|
|
@ -962,7 +962,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
.node-parameters-wrapper {
|
.node-parameters-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0 20px 200px 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dragging {
|
&.dragging {
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
</n8n-text>
|
</n8n-text>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #recovered-artifical-output-data>
|
<template #recovered-artificial-output-data>
|
||||||
<div :class="$style.recoveredOutputData">
|
<div :class="$style.recoveredOutputData">
|
||||||
<n8n-text tag="div" :bold="true" color="text-dark" size="large">{{
|
<n8n-text tag="div" :bold="true" color="text-dark" size="large">{{
|
||||||
$locale.baseText('executionDetails.executionFailed.recoveredNodeTitle')
|
$locale.baseText('executionDetails.executionFailed.recoveredNodeTitle')
|
||||||
|
|
|
@ -51,17 +51,28 @@
|
||||||
remoteParameterOptionsLoadingIssues !== null
|
remoteParameterOptionsLoadingIssues !== null
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<code-edit
|
<el-dialog
|
||||||
v-if="codeEditDialogVisible"
|
v-if="codeEditDialogVisible"
|
||||||
:value="value"
|
visible
|
||||||
:parameter="parameter"
|
append-to-body
|
||||||
:type="editorType"
|
:close-on-click-modal="false"
|
||||||
:codeAutocomplete="codeAutocomplete"
|
width="80%"
|
||||||
:path="path"
|
:title="`${$locale.baseText('codeEdit.edit')} ${$locale
|
||||||
:readonly="isReadOnly"
|
.nodeText()
|
||||||
@closeDialog="closeCodeEditDialog"
|
.inputLabelDisplayName(parameter, path)}`"
|
||||||
@valueChanged="expressionUpdated"
|
:before-close="closeCodeEditDialog"
|
||||||
></code-edit>
|
>
|
||||||
|
<div class="ignore-key-press">
|
||||||
|
<code-node-editor
|
||||||
|
:value="value"
|
||||||
|
:defaultValue="parameter.default"
|
||||||
|
:language="editorLanguage"
|
||||||
|
:isReadOnly="isReadOnly"
|
||||||
|
@valueChanged="expressionUpdated"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<text-edit
|
<text-edit
|
||||||
:dialogVisible="textEditDialogVisible"
|
:dialogVisible="textEditDialogVisible"
|
||||||
:value="value"
|
:value="value"
|
||||||
|
@ -73,15 +84,17 @@
|
||||||
></text-edit>
|
></text-edit>
|
||||||
|
|
||||||
<code-node-editor
|
<code-node-editor
|
||||||
v-if="getArgument('editor') === 'codeNodeEditor' && isCodeNode(node)"
|
v-if="editorType === 'codeNodeEditor' && isCodeNode(node)"
|
||||||
:mode="node.parameters.mode"
|
:mode="node.parameters.mode"
|
||||||
:jsCode="node.parameters.jsCode"
|
:value="node.parameters.jsCode"
|
||||||
|
:defaultValue="parameter.default"
|
||||||
|
:language="editorLanguage"
|
||||||
:isReadOnly="isReadOnly"
|
:isReadOnly="isReadOnly"
|
||||||
@valueChanged="valueChangedDebounced"
|
@valueChanged="valueChangedDebounced"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<html-editor
|
<html-editor
|
||||||
v-else-if="getArgument('editor') === 'htmlEditor'"
|
v-else-if="editorType === 'htmlEditor'"
|
||||||
:html="node.parameters.html"
|
:html="node.parameters.html"
|
||||||
:isReadOnly="isReadOnly"
|
:isReadOnly="isReadOnly"
|
||||||
:rows="getArgument('rows')"
|
:rows="getArgument('rows')"
|
||||||
|
@ -91,17 +104,16 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-else-if="isEditor === true"
|
v-else-if="editorType"
|
||||||
class="code-edit clickable ph-no-capture"
|
class="readonly-code clickable ph-no-capture"
|
||||||
@click="displayEditDialog()"
|
@click="displayEditDialog()"
|
||||||
>
|
>
|
||||||
<prism-editor
|
<code-node-editor
|
||||||
v-if="!codeEditDialogVisible"
|
v-if="!codeEditDialogVisible"
|
||||||
:lineNumbers="true"
|
:value="value"
|
||||||
:readonly="true"
|
:language="editorLanguage"
|
||||||
:code="displayValue"
|
:isReadOnly="true"
|
||||||
language="js"
|
/>
|
||||||
></prism-editor>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<n8n-input
|
<n8n-input
|
||||||
|
@ -338,10 +350,11 @@ import type {
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
INodePropertyCollection,
|
INodePropertyCollection,
|
||||||
NodeParameterValueType,
|
NodeParameterValueType,
|
||||||
|
EditorType,
|
||||||
|
CodeNodeEditorLanguage,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeHelpers } from 'n8n-workflow';
|
import { NodeHelpers } from 'n8n-workflow';
|
||||||
|
|
||||||
import CodeEdit from '@/components/CodeEdit.vue';
|
|
||||||
import CredentialsSelect from '@/components/CredentialsSelect.vue';
|
import CredentialsSelect from '@/components/CredentialsSelect.vue';
|
||||||
import ImportParameter from '@/components/ImportParameter.vue';
|
import ImportParameter from '@/components/ImportParameter.vue';
|
||||||
import ExpressionEdit from '@/components/ExpressionEdit.vue';
|
import ExpressionEdit from '@/components/ExpressionEdit.vue';
|
||||||
|
@ -351,8 +364,6 @@ import ParameterOptions from '@/components/ParameterOptions.vue';
|
||||||
import ParameterIssues from '@/components/ParameterIssues.vue';
|
import ParameterIssues from '@/components/ParameterIssues.vue';
|
||||||
import ResourceLocator from '@/components/ResourceLocator/ResourceLocator.vue';
|
import ResourceLocator from '@/components/ResourceLocator/ResourceLocator.vue';
|
||||||
import ExpressionParameterInput from '@/components/ExpressionParameterInput.vue';
|
import ExpressionParameterInput from '@/components/ExpressionParameterInput.vue';
|
||||||
// @ts-ignore
|
|
||||||
import PrismEditor from 'vue-prism-editor';
|
|
||||||
import TextEdit from '@/components/TextEdit.vue';
|
import TextEdit from '@/components/TextEdit.vue';
|
||||||
import CodeNodeEditor from '@/components/CodeNodeEditor/CodeNodeEditor.vue';
|
import CodeNodeEditor from '@/components/CodeNodeEditor/CodeNodeEditor.vue';
|
||||||
import HtmlEditor from '@/components/HtmlEditor/HtmlEditor.vue';
|
import HtmlEditor from '@/components/HtmlEditor/HtmlEditor.vue';
|
||||||
|
@ -385,14 +396,12 @@ export default mixins(
|
||||||
).extend({
|
).extend({
|
||||||
name: 'parameter-input',
|
name: 'parameter-input',
|
||||||
components: {
|
components: {
|
||||||
CodeEdit,
|
|
||||||
CodeNodeEditor,
|
CodeNodeEditor,
|
||||||
HtmlEditor,
|
HtmlEditor,
|
||||||
ExpressionEdit,
|
ExpressionEdit,
|
||||||
ExpressionParameterInput,
|
ExpressionParameterInput,
|
||||||
NodeCredentials,
|
NodeCredentials,
|
||||||
CredentialsSelect,
|
CredentialsSelect,
|
||||||
PrismEditor,
|
|
||||||
ScopesNotice,
|
ScopesNotice,
|
||||||
ParameterOptions,
|
ParameterOptions,
|
||||||
ParameterIssues,
|
ParameterIssues,
|
||||||
|
@ -554,8 +563,8 @@ export default mixins(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
node(): INodeUi | null {
|
node(): INodeUi {
|
||||||
return this.ndvStore.activeNode;
|
return this.ndvStore.activeNode!;
|
||||||
},
|
},
|
||||||
displayTitle(): string {
|
displayTitle(): string {
|
||||||
const interpolation = { interpolate: { shortPath: this.shortPath } };
|
const interpolation = { interpolate: { shortPath: this.shortPath } };
|
||||||
|
@ -636,7 +645,7 @@ export default mixins(
|
||||||
return 'textarea';
|
return 'textarea';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.parameter.typeOptions && this.parameter.typeOptions.editor === 'code') {
|
if (this.editorType === 'code') {
|
||||||
return 'textarea';
|
return 'textarea';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,11 +728,12 @@ export default mixins(
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
isEditor(): boolean {
|
editorType(): EditorType {
|
||||||
return ['code', 'json'].includes(this.editorType);
|
return this.getArgument('editor') as EditorType;
|
||||||
},
|
},
|
||||||
editorType(): string {
|
editorLanguage(): CodeNodeEditorLanguage {
|
||||||
return this.getArgument('editor') as string;
|
if (this.editorType === 'json' || this.parameter.type === 'json') return 'json';
|
||||||
|
return 'javaScript';
|
||||||
},
|
},
|
||||||
parameterOptions():
|
parameterOptions():
|
||||||
| Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>
|
| Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>
|
||||||
|
@ -907,22 +917,14 @@ export default mixins(
|
||||||
this.textEditDialogVisible = false;
|
this.textEditDialogVisible = false;
|
||||||
},
|
},
|
||||||
displayEditDialog() {
|
displayEditDialog() {
|
||||||
if (this.isEditor) {
|
if (this.editorType) {
|
||||||
this.codeEditDialogVisible = true;
|
this.codeEditDialogVisible = true;
|
||||||
} else {
|
} else {
|
||||||
this.textEditDialogVisible = true;
|
this.textEditDialogVisible = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getArgument(argumentName: string): string | number | boolean | undefined {
|
getArgument(argumentName: string): string | number | boolean | undefined {
|
||||||
if (this.parameter.typeOptions === undefined) {
|
return this.parameter.typeOptions?.[argumentName];
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.parameter.typeOptions[argumentName] === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.parameter.typeOptions[argumentName];
|
|
||||||
},
|
},
|
||||||
expressionUpdated(value: string) {
|
expressionUpdated(value: string) {
|
||||||
const val: NodeParameterValueType = this.isResourceLocatorParameter
|
const val: NodeParameterValueType = this.isResourceLocatorParameter
|
||||||
|
@ -1167,32 +1169,6 @@ export default mixins(
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true },
|
{ deep: true, immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reload function on change element from
|
|
||||||
// displayOptions.typeOptions.reloadOnChange parameters
|
|
||||||
if (this.parameter.typeOptions && this.parameter.typeOptions.reloadOnChange) {
|
|
||||||
// Get all parameter in reloadOnChange property
|
|
||||||
// This reload when parameters in reloadOnChange is updated
|
|
||||||
const parametersOnChange: string[] = this.parameter.typeOptions.reloadOnChange;
|
|
||||||
for (let i = 0; i < parametersOnChange.length; i++) {
|
|
||||||
const parameter = parametersOnChange[i] as string;
|
|
||||||
if (parameter in this.node.parameters) {
|
|
||||||
this.$watch(
|
|
||||||
() => {
|
|
||||||
if (this.node && this.node.parameters && this.node.parameters[parameter]) {
|
|
||||||
return this.node.parameters![parameter];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
this.loadRemoteParameterOptions();
|
|
||||||
},
|
|
||||||
{ deep: true, immediate: true },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$externalHooks().run('parameterInput.mount', {
|
this.$externalHooks().run('parameterInput.mount', {
|
||||||
|
@ -1204,7 +1180,7 @@ export default mixins(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.code-edit {
|
.readonly-code {
|
||||||
font-size: var(--font-size-xs);
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,11 +70,7 @@ export default defineComponent({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.parameter.typeOptions?.editor === 'codeNodeEditor') {
|
||||||
this.parameter.typeOptions &&
|
|
||||||
this.parameter.typeOptions.editor &&
|
|
||||||
this.parameter.typeOptions.editor === 'codeNodeEditor'
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.container">
|
<div :class="['run-data', $style.container]">
|
||||||
<n8n-callout
|
<n8n-callout
|
||||||
v-if="canPinData && hasPinData && !editMode.enabled && !isProductionExecutionPreview"
|
v-if="canPinData && hasPinData && !editMode.enabled && !isProductionExecutionPreview"
|
||||||
theme="secondary"
|
theme="secondary"
|
||||||
|
@ -190,11 +190,10 @@
|
||||||
|
|
||||||
<div v-else-if="editMode.enabled" :class="$style.editMode">
|
<div v-else-if="editMode.enabled" :class="$style.editMode">
|
||||||
<div :class="[$style.editModeBody, 'ignore-key-press']">
|
<div :class="[$style.editModeBody, 'ignore-key-press']">
|
||||||
<code-editor
|
<code-node-editor
|
||||||
:value="editMode.value"
|
:value="editMode.value"
|
||||||
:options="{ scrollBeyondLastLine: false }"
|
language="json"
|
||||||
type="json"
|
@valueChanged="ndvStore.setOutputPanelEditModeValue($event)"
|
||||||
@input="ndvStore.setOutputPanelEditModeValue($event)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.editModeFooter">
|
<div :class="$style.editModeFooter">
|
||||||
|
@ -228,7 +227,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="hasNodeRun && isArtificialRecoveredEventItem" :class="$style.center">
|
<div v-else-if="hasNodeRun && isArtificialRecoveredEventItem" :class="$style.center">
|
||||||
<slot name="recovered-artifical-output-data"></slot>
|
<slot name="recovered-artificial-output-data"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="hasNodeRun && hasRunError" :class="$style.stretchVertically">
|
<div v-else-if="hasNodeRun && hasRunError" :class="$style.stretchVertically">
|
||||||
|
@ -501,7 +500,7 @@ import { externalHooks } from '@/mixins/externalHooks';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||||
import { nodeHelpers } from '@/mixins/nodeHelpers';
|
import { nodeHelpers } from '@/mixins/nodeHelpers';
|
||||||
import { pinData } from '@/mixins/pinData';
|
import { pinData } from '@/mixins/pinData';
|
||||||
import { CodeEditor } from '@/components/forms';
|
import CodeNodeEditor from '@/components/CodeNodeEditor/CodeNodeEditor.vue';
|
||||||
import { dataPinningEventBus } from '@/event-bus';
|
import { dataPinningEventBus } from '@/event-bus';
|
||||||
import { clearJsonKey, executionDataToJson, stringSizeInBytes } from '@/utils';
|
import { clearJsonKey, executionDataToJson, stringSizeInBytes } from '@/utils';
|
||||||
import { isEmpty } from '@/utils';
|
import { isEmpty } from '@/utils';
|
||||||
|
@ -525,7 +524,7 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
|
||||||
BinaryDataDisplay,
|
BinaryDataDisplay,
|
||||||
NodeErrorView,
|
NodeErrorView,
|
||||||
WarningTooltip,
|
WarningTooltip,
|
||||||
CodeEditor,
|
CodeNodeEditor,
|
||||||
RunDataTable,
|
RunDataTable,
|
||||||
RunDataJson,
|
RunDataJson,
|
||||||
RunDataSchema,
|
RunDataSchema,
|
||||||
|
@ -1571,28 +1570,30 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
|
||||||
}
|
}
|
||||||
|
|
||||||
.editMode {
|
.editMode {
|
||||||
height: calc(100% - var(--spacing-s));
|
height: 100%;
|
||||||
|
max-height: calc(100% - var(--spacing-3xl));
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: stretch;
|
||||||
align-items: flex-end;
|
|
||||||
padding-left: var(--spacing-s);
|
padding-left: var(--spacing-s);
|
||||||
padding-right: var(--spacing-s);
|
padding-right: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editModeBody {
|
.editModeBody {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
max-height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
overflow: auto;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.editModeFooter {
|
.editModeFooter {
|
||||||
|
flex: 0 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: var(--spacing-s);
|
padding-top: var(--spacing-s);
|
||||||
|
padding-bottom: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editModeFooterInfotip {
|
.editModeFooterInfotip {
|
||||||
|
@ -1617,3 +1618,11 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.run-data {
|
||||||
|
.code-node-editor {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
<template>
|
|
||||||
<div ref="code" class="text-editor ph-no-capture" @keydown.stop />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import * as monaco from 'monaco-editor';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: 'code',
|
|
||||||
},
|
|
||||||
readonly: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
autocomplete: {
|
|
||||||
type: Function,
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
monacoInstance: null as monaco.editor.IStandaloneCodeEditor | null,
|
|
||||||
monacoLibrary: null as monaco.IDisposable | null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
loadEditor() {
|
|
||||||
if (!this.$refs.code) return;
|
|
||||||
|
|
||||||
this.monacoInstance = monaco.editor.create(this.$refs.code as HTMLElement, {
|
|
||||||
automaticLayout: true,
|
|
||||||
value: this.value,
|
|
||||||
language: this.type === 'code' ? 'javascript' : 'json',
|
|
||||||
tabSize: 2,
|
|
||||||
wordBasedSuggestions: false,
|
|
||||||
readOnly: this.readonly,
|
|
||||||
padding: {
|
|
||||||
top: 16,
|
|
||||||
},
|
|
||||||
minimap: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
...this.options,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.monacoInstance.onDidChangeModelContent(() => {
|
|
||||||
const model = this.monacoInstance!.getModel();
|
|
||||||
if (model) {
|
|
||||||
this.$emit('input', model.getValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const darkModeBetaEnabled =
|
|
||||||
document.body.classList.contains('theme-dark-beta') &&
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
||||||
|
|
||||||
monaco.editor.defineTheme('n8nCustomTheme', {
|
|
||||||
base: darkModeBetaEnabled ? 'vs-dark' : 'vs',
|
|
||||||
inherit: true,
|
|
||||||
rules: [],
|
|
||||||
colors: {},
|
|
||||||
});
|
|
||||||
monaco.editor.setTheme('n8nCustomTheme');
|
|
||||||
|
|
||||||
if (this.type === 'code') {
|
|
||||||
// As wordBasedSuggestions: false does not have any effect does it however seem
|
|
||||||
// to remove all all suggestions from the editor if I do this
|
|
||||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
|
||||||
allowNonTsExtensions: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.autocomplete) {
|
|
||||||
this.monacoLibrary = monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
|
||||||
this.autocomplete().join('\n'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (this.type === 'json') {
|
|
||||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
||||||
validate: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleResize() {
|
|
||||||
if (this.monacoInstance) {
|
|
||||||
// Workaround to force Monaco to recompute its boundaries
|
|
||||||
this.monacoInstance.layout({} as unknown as undefined);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
setTimeout(this.loadEditor);
|
|
||||||
window.addEventListener('resize', this.handleResize);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
if (this.monacoLibrary) {
|
|
||||||
this.monacoLibrary.dispose();
|
|
||||||
}
|
|
||||||
window.removeEventListener('resize', this.handleResize);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.text-editor {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
border: 1px solid var(--color-foreground-base);
|
|
||||||
border-radius: var(--border-radius-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep {
|
|
||||||
.monaco-editor {
|
|
||||||
.slider {
|
|
||||||
border-radius: var(--border-radius-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
&,
|
|
||||||
&-background,
|
|
||||||
.inputarea.ime-input,
|
|
||||||
.margin {
|
|
||||||
border-radius: var(--border-radius-base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1 +0,0 @@
|
||||||
export { default as CodeEditor } from './CodeEditor.vue';
|
|
|
@ -3,9 +3,6 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
import './plugins';
|
import './plugins';
|
||||||
import 'prismjs';
|
|
||||||
import 'prismjs/themes/prism.css';
|
|
||||||
import 'vue-prism-editor/dist/VuePrismEditor.css';
|
|
||||||
import 'vue-json-pretty/lib/styles.css';
|
import 'vue-json-pretty/lib/styles.css';
|
||||||
import '@jsplumb/browser-ui/css/jsplumbtoolkit.css';
|
import '@jsplumb/browser-ui/css/jsplumbtoolkit.css';
|
||||||
import 'n8n-design-system/css/index.scss';
|
import 'n8n-design-system/css/index.scss';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import vue from '@vitejs/plugin-vue2';
|
import vue from '@vitejs/plugin-vue2';
|
||||||
import legacy from '@vitejs/plugin-legacy';
|
import legacy from '@vitejs/plugin-legacy';
|
||||||
import monacoEditorPlugin from 'vite-plugin-monaco-editor';
|
|
||||||
import path, { resolve } from 'path';
|
import path, { resolve } from 'path';
|
||||||
import { defineConfig, mergeConfig } from 'vite';
|
import { defineConfig, mergeConfig } from 'vite';
|
||||||
import { defineConfig as defineVitestConfig } from 'vitest/config';
|
import { defineConfig as defineVitestConfig } from 'vitest/config';
|
||||||
|
@ -73,24 +72,11 @@ const alias = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// https://github.com/vitest-dev/vitest/discussions/1806
|
|
||||||
if (NODE_ENV === 'test') {
|
|
||||||
alias.push({
|
|
||||||
find: /^monaco-editor$/,
|
|
||||||
replacement: __dirname + '/node_modules/monaco-editor/esm/vs/editor/editor.api',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
vue(),
|
vue(),
|
||||||
legacy({
|
legacy({
|
||||||
targets: ['>1%', 'last 3 versions', 'not dead'],
|
targets: ['>1%', 'last 3 versions', 'not dead'],
|
||||||
}),
|
}),
|
||||||
monacoEditorPlugin({
|
|
||||||
publicPath: 'assets/monaco-editor',
|
|
||||||
customDistPath: (root: string, buildOutDir: string, base: string) =>
|
|
||||||
`${root}/${buildOutDir}/assets/monaco-editor`,
|
|
||||||
}),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const { SENTRY_AUTH_TOKEN: authToken, RELEASE: release } = process.env;
|
const { SENTRY_AUTH_TOKEN: authToken, RELEASE: release } = process.env;
|
||||||
|
|
|
@ -1019,7 +1019,8 @@ export type NodePropertyTypes =
|
||||||
|
|
||||||
export type CodeAutocompleteTypes = 'function' | 'functionItem';
|
export type CodeAutocompleteTypes = 'function' | 'functionItem';
|
||||||
|
|
||||||
export type EditorTypes = 'code' | 'codeNodeEditor' | 'htmlEditor' | 'json';
|
export type EditorType = 'code' | 'codeNodeEditor' | 'htmlEditor' | 'json';
|
||||||
|
export type CodeNodeEditorLanguage = 'javaScript' | 'json'; //| 'python' | 'sql';
|
||||||
|
|
||||||
export interface ILoadOptions {
|
export interface ILoadOptions {
|
||||||
routing?: {
|
routing?: {
|
||||||
|
@ -1032,7 +1033,8 @@ export interface ILoadOptions {
|
||||||
export interface INodePropertyTypeOptions {
|
export interface INodePropertyTypeOptions {
|
||||||
alwaysOpenEditWindow?: boolean; // Supported by: json
|
alwaysOpenEditWindow?: boolean; // Supported by: json
|
||||||
codeAutocomplete?: CodeAutocompleteTypes; // Supported by: string
|
codeAutocomplete?: CodeAutocompleteTypes; // Supported by: string
|
||||||
editor?: EditorTypes; // Supported by: string
|
editor?: EditorType; // Supported by: string
|
||||||
|
editorLanguage?: CodeNodeEditorLanguage; // Supported by: string in combination with editor: codeNodeEditor
|
||||||
loadOptionsDependsOn?: string[]; // Supported by: options
|
loadOptionsDependsOn?: string[]; // Supported by: options
|
||||||
loadOptionsMethod?: string; // Supported by: options
|
loadOptionsMethod?: string; // Supported by: options
|
||||||
loadOptions?: ILoadOptions; // Supported by: options
|
loadOptions?: ILoadOptions; // Supported by: options
|
||||||
|
|
100
pnpm-lock.yaml
100
pnpm-lock.yaml
|
@ -841,6 +841,9 @@ importers:
|
||||||
'@codemirror/lang-javascript':
|
'@codemirror/lang-javascript':
|
||||||
specifier: ^6.1.2
|
specifier: ^6.1.2
|
||||||
version: 6.1.2
|
version: 6.1.2
|
||||||
|
'@codemirror/lang-json':
|
||||||
|
specifier: ^6.0.1
|
||||||
|
version: 6.0.1
|
||||||
'@codemirror/language':
|
'@codemirror/language':
|
||||||
specifier: ^6.2.1
|
specifier: ^6.2.1
|
||||||
version: 6.2.1
|
version: 6.2.1
|
||||||
|
@ -928,9 +931,6 @@ importers:
|
||||||
luxon:
|
luxon:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
monaco-editor:
|
|
||||||
specifier: ^0.33.0
|
|
||||||
version: 0.33.0
|
|
||||||
n8n-design-system:
|
n8n-design-system:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../design-system
|
version: link:../design-system
|
||||||
|
@ -946,9 +946,6 @@ importers:
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^2.8.3
|
specifier: ^2.8.3
|
||||||
version: 2.8.3
|
version: 2.8.3
|
||||||
prismjs:
|
|
||||||
specifier: ^1.17.1
|
|
||||||
version: 1.17.1
|
|
||||||
stream-browserify:
|
stream-browserify:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
|
@ -979,9 +976,6 @@ importers:
|
||||||
vue-json-pretty:
|
vue-json-pretty:
|
||||||
specifier: 1.9.3
|
specifier: 1.9.3
|
||||||
version: 1.9.3
|
version: 1.9.3
|
||||||
vue-prism-editor:
|
|
||||||
specifier: ^0.3.0
|
|
||||||
version: 0.3.0
|
|
||||||
vue-router:
|
vue-router:
|
||||||
specifier: ^3.6.5
|
specifier: ^3.6.5
|
||||||
version: 3.6.5(vue@2.7.14)
|
version: 3.6.5(vue@2.7.14)
|
||||||
|
@ -1088,9 +1082,6 @@ importers:
|
||||||
vite:
|
vite:
|
||||||
specifier: 4.0.4
|
specifier: 4.0.4
|
||||||
version: 4.0.4(@types/node@16.18.12)(sass@1.55.0)(terser@5.16.1)
|
version: 4.0.4(@types/node@16.18.12)(sass@1.55.0)(terser@5.16.1)
|
||||||
vite-plugin-monaco-editor:
|
|
||||||
specifier: ^1.0.10
|
|
||||||
version: 1.0.10(monaco-editor@0.33.0)
|
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.5
|
specifier: ^0.28.5
|
||||||
version: 0.28.5(sass@1.55.0)(terser@5.16.1)
|
version: 0.28.5(sass@1.55.0)(terser@5.16.1)
|
||||||
|
@ -3369,6 +3360,13 @@ packages:
|
||||||
'@lezer/javascript': 1.0.2
|
'@lezer/javascript': 1.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@codemirror/lang-json@6.0.1:
|
||||||
|
resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.2.1
|
||||||
|
'@lezer/json': 1.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@codemirror/language@6.2.1:
|
/@codemirror/language@6.2.1:
|
||||||
resolution: {integrity: sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==}
|
resolution: {integrity: sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -4232,6 +4230,13 @@ packages:
|
||||||
'@lezer/lr': 1.2.3
|
'@lezer/lr': 1.2.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@lezer/json@1.0.0:
|
||||||
|
resolution: {integrity: sha512-zbAuUY09RBzCoCA3lJ1+ypKw5WSNvLqGMtasdW6HvVOqZoCpPr8eWrsGnOVWGKGn8Rh21FnrKRVlJXrGAVUqRw==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.1
|
||||||
|
'@lezer/lr': 1.2.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@lezer/lr@1.2.3:
|
/@lezer/lr@1.2.3:
|
||||||
resolution: {integrity: sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==}
|
resolution: {integrity: sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -9373,15 +9378,6 @@ packages:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/clipboard@2.0.11:
|
|
||||||
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
|
|
||||||
dependencies:
|
|
||||||
good-listener: 1.2.2
|
|
||||||
select: 1.1.2
|
|
||||||
tiny-emitter: 2.1.0
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/cliui@3.2.0:
|
/cliui@3.2.0:
|
||||||
resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==}
|
resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -9615,18 +9611,10 @@ packages:
|
||||||
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
|
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/component-props@1.1.1:
|
|
||||||
resolution: {integrity: sha512-69pIRJs9fCCHRqCz3390YF2LV1Lu6iEMZ5zuVqqUn+G20V9BNXlMs0cWawWeW9g4Ynmg29JmkG6R7/lUJoGd1Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/component-type@1.2.1:
|
/component-type@1.2.1:
|
||||||
resolution: {integrity: sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg==}
|
resolution: {integrity: sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/component-xor@0.0.4:
|
|
||||||
resolution: {integrity: sha512-ZIt6sla8gfo+AFVRZoZOertcnD5LJaY2T9CKE2j13NJxQt/mUafD69Bl7/Y4AnpI2LGjiXH7cOfJDx/n2G9edA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/compressible@2.0.18:
|
/compressible@2.0.18:
|
||||||
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
|
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
@ -10540,11 +10528,6 @@ packages:
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
/delegate@3.2.0:
|
|
||||||
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/delegates@1.0.0:
|
/delegates@1.0.0:
|
||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
|
|
||||||
|
@ -10691,13 +10674,6 @@ packages:
|
||||||
resolution: {integrity: sha512-jNCX+uNJ3v38BKvPbpki6j5ItVlnSqVV6vDWGS6rExzCMjsc39frLjm1n91o6YaKK6AZl0wLloItW6C6mr61BQ==}
|
resolution: {integrity: sha512-jNCX+uNJ3v38BKvPbpki6j5ItVlnSqVV6vDWGS6rExzCMjsc39frLjm1n91o6YaKK6AZl0wLloItW6C6mr61BQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/dom-iterator@1.0.0:
|
|
||||||
resolution: {integrity: sha512-7dsMOQI07EMU98gQM8NSB3GsAiIeBYIPKpnxR3c9xOvdvBjChAcOM0iJ222I3p5xyiZO9e5oggkNaCusuTdYig==}
|
|
||||||
dependencies:
|
|
||||||
component-props: 1.1.1
|
|
||||||
component-xor: 0.0.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/dom-serializer@0.2.2:
|
/dom-serializer@0.2.2:
|
||||||
resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==}
|
resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -12824,13 +12800,6 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/good-listener@1.2.2:
|
|
||||||
resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==}
|
|
||||||
dependencies:
|
|
||||||
delegate: 3.2.0
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/google-timezones-json@1.1.0:
|
/google-timezones-json@1.1.0:
|
||||||
resolution: {integrity: sha512-6BmBx9gJVALV2jsfMks8PwmkWT5ip3+bmMyTgXu4PY+G8nKjHi61yrL7rSXpMYRsIzUXhVKpj+MnjhnwG9nung==}
|
resolution: {integrity: sha512-6BmBx9gJVALV2jsfMks8PwmkWT5ip3+bmMyTgXu4PY+G8nKjHi61yrL7rSXpMYRsIzUXhVKpj+MnjhnwG9nung==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -16126,9 +16095,6 @@ packages:
|
||||||
/moment@2.29.4:
|
/moment@2.29.4:
|
||||||
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
|
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
|
||||||
|
|
||||||
/monaco-editor@0.33.0:
|
|
||||||
resolution: {integrity: sha512-VcRWPSLIUEgQJQIE0pVT8FcGBIgFoxz7jtqctE+IiCxWugD0DwgyQBcZBhdSrdMC84eumoqMZsGl2GTreOzwqw==}
|
|
||||||
|
|
||||||
/mongodb-connection-string-url@2.5.4:
|
/mongodb-connection-string-url@2.5.4:
|
||||||
resolution: {integrity: sha512-SeAxuWs0ez3iI3vvmLk/j2y+zHwigTDKQhtdxTgt5ZCOQQS5+HW4g45/Xw5vzzbn7oQXCNQ24Z40AkJsizEy7w==}
|
resolution: {integrity: sha512-SeAxuWs0ez3iI3vvmLk/j2y+zHwigTDKQhtdxTgt5ZCOQQS5+HW4g45/Xw5vzzbn7oQXCNQ24Z40AkJsizEy7w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -17812,12 +17778,6 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/prismjs@1.17.1:
|
|
||||||
resolution: {integrity: sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==}
|
|
||||||
optionalDependencies:
|
|
||||||
clipboard: 2.0.11
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/process-nextick-args@2.0.1:
|
/process-nextick-args@2.0.1:
|
||||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||||
|
|
||||||
|
@ -19075,11 +19035,6 @@ packages:
|
||||||
parseley: 0.7.0
|
parseley: 0.7.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/select@1.1.2:
|
|
||||||
resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/semver-greatest-satisfied-range@1.1.0:
|
/semver-greatest-satisfied-range@1.1.0:
|
||||||
resolution: {integrity: sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==}
|
resolution: {integrity: sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
@ -20370,11 +20325,6 @@ packages:
|
||||||
resolution: {integrity: sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==}
|
resolution: {integrity: sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/tiny-emitter@2.1.0:
|
|
||||||
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/tiny-glob@0.2.9:
|
/tiny-glob@0.2.9:
|
||||||
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -21458,14 +21408,6 @@ packages:
|
||||||
- terser
|
- terser
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-monaco-editor@1.0.10(monaco-editor@0.33.0):
|
|
||||||
resolution: {integrity: sha512-7yTAFIE0SefjCmfnjrvXOl53wkxeSASc/ZIcB5tZeEK3vAmHhveV8y3f90Vp8b+PYdbUipjqf91mbFbSENkpcw==}
|
|
||||||
peerDependencies:
|
|
||||||
monaco-editor: 0.29.x
|
|
||||||
dependencies:
|
|
||||||
monaco-editor: 0.33.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vite@4.0.4(@types/node@16.18.12)(sass@1.55.0)(terser@5.16.1):
|
/vite@4.0.4(@types/node@16.18.12)(sass@1.55.0)(terser@5.16.1):
|
||||||
resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
|
resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
|
@ -21840,14 +21782,6 @@ packages:
|
||||||
- whiskers
|
- whiskers
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vue-prism-editor@0.3.0:
|
|
||||||
resolution: {integrity: sha512-yNSuwql/xHMJrWghn/OhZ5WPBKdhx7FkvFjgq2uDm99jHSJhuGwhcgPyuoGzpm6w8DRDzi85lgerKCu8DTDWWg==}
|
|
||||||
dependencies:
|
|
||||||
dom-iterator: 1.0.0
|
|
||||||
escape-html: 1.0.3
|
|
||||||
unescape: 1.0.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/vue-property-decorator@9.1.2(vue-class-component@7.2.6)(vue@2.7.14):
|
/vue-property-decorator@9.1.2(vue-class-component@7.2.6)(vue@2.7.14):
|
||||||
resolution: {integrity: sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==}
|
resolution: {integrity: sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
Loading…
Reference in a new issue