diff --git a/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue b/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue index 895e79caf2..8919a068a0 100644 --- a/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue +++ b/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue @@ -8,10 +8,16 @@ import prettier from 'prettier/standalone'; import htmlParser from 'prettier/parser-html'; import cssParser from 'prettier/parser-postcss'; import jsParser from 'prettier/parser-babel'; -import { html } from 'codemirror-lang-html-n8n'; +import { htmlLanguage, autoCloseTags, html } from 'codemirror-lang-html-n8n'; import { autocompletion } from '@codemirror/autocomplete'; import { indentWithTab, insertNewlineAndIndent, history } from '@codemirror/commands'; -import { bracketMatching, ensureSyntaxTree, foldGutter, indentOnInput } from '@codemirror/language'; +import { + bracketMatching, + ensureSyntaxTree, + foldGutter, + indentOnInput, + LanguageSupport, +} from '@codemirror/language'; import { EditorState, Extension } from '@codemirror/state'; import { dropCursor, @@ -23,6 +29,7 @@ import { ViewUpdate, } from '@codemirror/view'; +import { n8nCompletionSources } from '@/plugins/codemirror/completions/addCompletions'; import { expressionInputHandler } from '@/plugins/codemirror/inputHandlers/expression.inputHandler'; import { highlighter } from '@/plugins/codemirror/resolvableHighlighter'; import { htmlEditorEventBus } from '@/event-bus/html-editor-event-bus'; @@ -50,6 +57,10 @@ export default mixins(expressionManager).extend({ type: Boolean, default: false, }, + disableExpressionCompletions: { + type: Boolean, + default: false, + }, }, data() { return { @@ -62,10 +73,18 @@ export default mixins(expressionManager).extend({ }, extensions(): Extension[] { + function htmlWithCompletions() { + return new LanguageSupport( + htmlLanguage, + n8nCompletionSources().map((source) => htmlLanguage.data.of(source)), + ); + } + return [ bracketMatching(), autocompletion(), - html({ autoCloseTags: true }), + this.disableExpressionCompletions ? html() : htmlWithCompletions(), + autoCloseTags, expressionInputHandler(), keymap.of([indentWithTab, { key: 'Enter', run: insertNewlineAndIndent }]), indentOnInput(), diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 358e34902d..d15faa9181 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -86,6 +86,7 @@ :isReadOnly="isReadOnly" :rows="getArgument('rows')" :disableExpressionColoring="!isHtmlNode(node)" + :disableExpressionCompletions="!isHtmlNode(node)" @valueChanged="valueChangedDebounced" /> diff --git a/packages/editor-ui/src/plugins/codemirror/completions/addCompletions.ts b/packages/editor-ui/src/plugins/codemirror/completions/addCompletions.ts new file mode 100644 index 0000000000..34076935e7 --- /dev/null +++ b/packages/editor-ui/src/plugins/codemirror/completions/addCompletions.ts @@ -0,0 +1,18 @@ +import { ifIn } from '@codemirror/autocomplete'; +import { blankCompletions } from './blank.completions'; +import { bracketAccessCompletions } from './bracketAccess.completions'; +import { datatypeCompletions } from './datatype.completions'; +import { dollarCompletions } from './dollar.completions'; +import { nonDollarCompletions } from './nonDollar.completions'; + +export function n8nCompletionSources() { + return [ + blankCompletions, + bracketAccessCompletions, + datatypeCompletions, + dollarCompletions, + nonDollarCompletions, + ].map((source) => ({ + autocomplete: ifIn(['Resolvable'], source), + })); +} diff --git a/packages/editor-ui/src/plugins/codemirror/n8nLang.ts b/packages/editor-ui/src/plugins/codemirror/n8nLang.ts index b72c332ab7..33cc5493d2 100644 --- a/packages/editor-ui/src/plugins/codemirror/n8nLang.ts +++ b/packages/editor-ui/src/plugins/codemirror/n8nLang.ts @@ -2,13 +2,8 @@ import { parserWithMetaData as n8nParser } from 'codemirror-lang-n8n-expression' import { LanguageSupport, LRLanguage } from '@codemirror/language'; import { parseMixed } from '@lezer/common'; import { javascriptLanguage } from '@codemirror/lang-javascript'; -import { ifIn } from '@codemirror/autocomplete'; -import { blankCompletions } from './completions/blank.completions'; -import { bracketAccessCompletions } from './completions/bracketAccess.completions'; -import { datatypeCompletions } from './completions/datatype.completions'; -import { dollarCompletions } from './completions/dollar.completions'; -import { nonDollarCompletions } from './completions/nonDollar.completions'; +import { n8nCompletionSources } from './completions/addCompletions'; const n8nParserWithNestedJsParser = n8nParser.configure({ wrap: parseMixed((node) => { @@ -23,16 +18,8 @@ const n8nParserWithNestedJsParser = n8nParser.configure({ const n8nLanguage = LRLanguage.define({ parser: n8nParserWithNestedJsParser }); export function n8nLang() { - const options = [ - blankCompletions, - bracketAccessCompletions, - datatypeCompletions, - dollarCompletions, - nonDollarCompletions, - ].map((group) => n8nLanguage.data.of({ autocomplete: ifIn(['Resolvable'], group) })); - return new LanguageSupport(n8nLanguage, [ n8nLanguage.data.of({ closeBrackets: { brackets: ['{', '('] } }), - ...options, + ...n8nCompletionSources().map((source) => n8nLanguage.data.of(source)), ]); }