Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(editor): Introduce proxy completions to expressions #5075

Merged
merged 14 commits into from
Jan 6, 2023
4 changes: 2 additions & 2 deletions packages/editor-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"test:dev": "vitest"
},
"dependencies": {
"@codemirror/autocomplete": "^6.1.0",
"@codemirror/autocomplete": "^6.4.0",
"@codemirror/commands": "^6.1.0",
"@codemirror/lang-javascript": "^6.0.2",
"@codemirror/lang-javascript": "^6.1.2",
"@codemirror/language": "^6.2.1",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.1.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@ import {
lineNumbers,
} from '@codemirror/view';
import { bracketMatching, foldGutter, indentOnInput } from '@codemirror/language';
import { acceptCompletion, closeBrackets } from '@codemirror/autocomplete';
import { acceptCompletion } from '@codemirror/autocomplete';
import {
history,
indentWithTab,
insertNewlineAndIndent,
toggleComment,
} from '@codemirror/commands';
import { lintGutter } from '@codemirror/lint';
import type { Extension } from '@codemirror/state';

import { customInputHandler } from './inputHandler';

const [_, bracketState] = closeBrackets() as readonly Extension[];
import { codeInputHandler } from '@/plugins/codemirror/inputHandlers/code.inputHandler';

export const baseExtensions = [
lineNumbers(),
Expand All @@ -29,7 +26,7 @@ export const baseExtensions = [
history(),
foldGutter(),
lintGutter(),
[customInputHandler, bracketState],
codeInputHandler(),
dropCursor(),
indentOnInput(),
bracketMatching(),
Expand Down
4 changes: 2 additions & 2 deletions packages/editor-ui/src/components/CodeNodeEditor/completer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const completerExtension = mixins(
// luxon
this.todayCompletions,
this.nowCompletions,
this.dateTimeCompltions,
this.dateTimeCompletions,

// item index
this.inputCompletions,
Expand Down Expand Up @@ -174,7 +174,7 @@ export const completerExtension = mixins(

if (value === '$now') return this.nowCompletions(context, variable);
if (value === '$today') return this.todayCompletions(context, variable);
if (value === 'DateTime') return this.dateTimeCompltions(context, variable);
if (value === 'DateTime') return this.dateTimeCompletions(context, variable);

// item index

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Vue from 'vue';
import { isAllowedInDotNotation, escape, toVariableOption } from '../utils';
import { escape, toVariableOption } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { IDataObject, IPinData, IRunData } from 'n8n-workflow';
import type { CodeNodeEditorMixin } from '../types';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows';
import { useNDVStore } from '@/stores/ndv';
import { isAllowedInDotNotation } from '@/plugins/codemirror/completions/utils';

export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
computed: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const luxonCompletions = (Vue as CodeNodeEditorMixin).extend({
/**
* Complete `DateTime` with luxon `DateTime` static methods.
*/
dateTimeCompltions(context: CompletionContext, matcher = 'DateTime'): CompletionResult | null {
dateTimeCompletions(context: CompletionContext, matcher = 'DateTime'): CompletionResult | null {
const pattern = new RegExp(`${escape(matcher)}\..*`);

const preCursor = context.matchBefore(pattern);
Expand Down
42 changes: 0 additions & 42 deletions packages/editor-ui/src/components/CodeNodeEditor/inputHandler.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/editor-ui/src/components/CodeNodeEditor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ export function walk<T extends RangeNode>(
return found as T[];
}

export const isAllowedInDotNotation = (str: string) => {
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()_+\-=[\]{};':"\\|,.<>?~]/g;

return !DOT_NOTATION_BANNED_CHARS.test(str);
};

export const escape = (str: string) =>
str
.replace('$', '\\$')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import { history } from '@codemirror/commands';

import { workflowHelpers } from '@/mixins/workflowHelpers';
import { expressionManager } from '@/mixins/expressionManager';
import { doubleBraceHandler } from '@/plugins/codemirror/doubleBraceHandler';
import { n8nLanguageSupport } from '@/plugins/codemirror/n8nLanguageSupport';
import { expressionInputHandler } from '@/plugins/codemirror/inputHandlers/expression.inputHandler';
import { n8nLang } from '@/plugins/codemirror/n8nLang';
import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { inputTheme } from './theme';

import type { IVariableItemSelected } from '@/Interface';
import { forceParse } from '@/utils/forceParse';
import { autocompletion } from '@codemirror/autocomplete';

export default mixins(expressionManager, workflowHelpers).extend({
name: 'ExpressionEditorModalInput',
Expand All @@ -36,9 +37,10 @@ export default mixins(expressionManager, workflowHelpers).extend({
mounted() {
const extensions = [
inputTheme(),
n8nLanguageSupport(),
autocompletion(),
n8nLang(),
history(),
doubleBraceHandler(),
expressionInputHandler(),
EditorView.lineWrapping,
EditorState.readOnly.of(this.isReadOnly),
EditorView.domEventHandlers({ scroll: forceParse }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { useNDVStore } from '@/stores/ndv';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { expressionManager } from '@/mixins/expressionManager';
import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { n8nLanguageSupport } from '@/plugins/codemirror/n8nLanguageSupport';
import { doubleBraceHandler } from '@/plugins/codemirror/doubleBraceHandler';
import { expressionInputHandler } from '@/plugins/codemirror/inputHandlers/expression.inputHandler';
import { inputTheme } from './theme';
import { autocompletion, ifIn } from '@codemirror/autocomplete';
import { n8nLang } from '@/plugins/codemirror/n8nLang';

export default mixins(expressionManager, workflowHelpers).extend({
name: 'InlineExpressionEditorInput',
Expand All @@ -39,35 +40,19 @@ export default mixins(expressionManager, workflowHelpers).extend({
},
watch: {
value(newValue) {
const payload: Record<string, unknown> = {
const isInternalChange = newValue === this.editor?.state.doc.toString();

if (isInternalChange) return;

// manual update on external change, e.g. from expression modal or mapping drop

this.editor?.dispatch({
changes: {
from: 0,
to: this.editor?.state.doc.length,
insert: newValue,
},
selection: { anchor: this.cursorPosition, head: this.cursorPosition },
};

/**
* If completion from selection, preserve selection.
*/
if (this.editor) {
const [range] = this.editor.state.selection.ranges;

const isBraceAutoinsertion =
this.editor.state.sliceDoc(range.from - 1, range.from) === '{' &&
this.editor.state.sliceDoc(range.to, range.to + 1) === '}';

if (isBraceAutoinsertion) {
payload.selection = { anchor: range.from, head: range.to };
}
}

try {
this.editor?.dispatch(payload);
} catch (_) {
// ignore out-of-range selection error on drop
}
});
},
ndvInputData() {
this.editor?.dispatch({
Expand All @@ -92,9 +77,10 @@ export default mixins(expressionManager, workflowHelpers).extend({
mounted() {
const extensions = [
inputTheme({ isSingleLine: this.isSingleLine }),
n8nLanguageSupport(),
autocompletion(),
n8nLang(),
history(),
doubleBraceHandler(),
expressionInputHandler(),
EditorView.lineWrapping,
EditorView.editable.of(!this.isReadOnly),
EditorView.domEventHandlers({
Expand Down
Loading