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(Code Node): Add Python support #4295

Merged
merged 254 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
254 commits
Select commit Hold shift + click to select a range
35556dd
:blue_book: Create types file
ivov Aug 30, 2022
c87f2b2
:truck: Rename theme
ivov Aug 30, 2022
62124c4
:fire: Remove unneeded prop
ivov Aug 30, 2022
d2f1960
:zap: Override keybindings
ivov Aug 30, 2022
8694c63
:zap: Expand lintings
ivov Aug 30, 2022
0b25559
:zap: Create editor content getter
ivov Aug 30, 2022
f35126c
:truck: Ensure all helpers use `$`
ivov Aug 30, 2022
f0d0185
:sparkles: Add autocompletion
ivov Aug 30, 2022
fbbdbda
:zap: Filter out welcome note node
ivov Aug 30, 2022
6c9bb1f
:zap: Convey error line number
ivov Aug 30, 2022
6e55e05
:zap: Highlight error line
ivov Aug 30, 2022
307b797
:zap: Restore logging from node
ivov Aug 30, 2022
fc402e7
:sparkles: More autocompletions
ivov Aug 30, 2022
105610e
:zap: Streamline completions
ivov Aug 31, 2022
92315a3
:pencil2: Update placeholders
ivov Aug 31, 2022
59b09ab
:zap: Update linter to new methods
ivov Aug 31, 2022
7a67a77
:fire: Remove `$nodeItem` completions
ivov Aug 31, 2022
2fd5597
:zap: Re-update placeholders
ivov Aug 31, 2022
e1708b7
:twisted_rightwards_arrows: Merge master
ivov Aug 31, 2022
f9e4d78
:art: Fix formatting
ivov Aug 31, 2022
a61492c
:package: Update `package-lock.json`
ivov Aug 31, 2022
238b8b3
:zap: Refresh with multi-line empty string
ivov Aug 31, 2022
cb737c0
:zap: Account for syntax errors
ivov Aug 31, 2022
a9d1227
:fire: Remove unneeded variant
ivov Aug 31, 2022
732ca58
:zap: Minor improvements
ivov Aug 31, 2022
2ac7bf0
:zap: Add more autocompletions
ivov Aug 31, 2022
d71629b
:truck: Rename extension
ivov Sep 1, 2022
0058d09
:fire: Remove outdated comments
ivov Sep 1, 2022
8ea43b2
:truck: Rename field
ivov Sep 1, 2022
e5eed49
:sparkles: More autocompletions
ivov Sep 1, 2022
87cbdc4
:zap: Fix up error display when empty text
ivov Sep 1, 2022
7b17042
:fire: Remove logging
ivov Sep 1, 2022
e59d2ab
:sparkles: More error validation
ivov Sep 1, 2022
bc9334e
:bug: Fix `pairedItem` to `pairedItem()`
ivov Sep 1, 2022
da86942
:zap: Add item to validation info
ivov Sep 1, 2022
e00e54c
:twisted_rightwards_arrows: Merge master
ivov Sep 11, 2022
62065a4
:package: Update `package-lock.json`
ivov Sep 11, 2022
98ae79b
:zap: Leftover fixes
ivov Sep 11, 2022
1c90e2b
:zap: Set `insertNewlineAndIndent`
ivov Sep 11, 2022
ee7790e
:package: Update `package-lock.json`
ivov Sep 14, 2022
dbec09a
:twisted_rightwards_arrows: Merge master
ivov Sep 14, 2022
86d32c2
:package: Re-update `package-lock.json`
ivov Sep 14, 2022
55508f4
:shirt: Add lint exception
ivov Sep 14, 2022
46f7adc
:blue_book: Add type to mixin type
ivov Sep 14, 2022
942b2f2
Clean up comment
ivov Sep 14, 2022
653b39f
:zap: Refactor completion per new requirements
ivov Sep 14, 2022
9e202b9
:zap: Adjust placeholders
ivov Sep 15, 2022
0ee8796
:zap: Add `json` autocompletions for `$input`
ivov Sep 15, 2022
622ab7a
:art: Set border
ivov Sep 15, 2022
55adfa3
:zap: Restore local completion source
ivov Sep 15, 2022
10b69fe
:zap: Implement autocompletion for imports
ivov Sep 15, 2022
58197f8
:zap: Add `.*` to follow user typing on autocompletion
ivov Sep 15, 2022
55bd59b
:blue_book: Fix typings in autocompletions
ivov Sep 15, 2022
70116a1
:shirt: Add linting for use of `item()`
ivov Sep 15, 2022
6b57813
:twisted_rightwards_arrows: Merge master
ivov Sep 15, 2022
14ba3cb
:package: Update `package-lock.json`
ivov Sep 15, 2022
bc2e336
:bug: Fix for `$items(nodeName)[0]`
ivov Sep 16, 2022
5f4d0a4
:zap: Filter down built-in modules list
ivov Sep 16, 2022
0b290b5
:zap: Refactor error handling
ivov Sep 16, 2022
1577a13
:zap: Linter and validation improvements
ivov Sep 16, 2022
740da9f
:zap: Apply review feedback
ivov Sep 16, 2022
f687bd1
:recycle: More general refactorings
ivov Sep 18, 2022
4a3db67
:zap: Add dot notation utility
ivov Sep 19, 2022
d9e2fad
Customize input handler
ivov Sep 19, 2022
f8931e0
:zap: Support `.json.` completions
ivov Sep 19, 2022
4b20bd8
:zap: Adjust placeholder
ivov Sep 19, 2022
1b0ed01
:zap: Sort imports
ivov Sep 19, 2022
5d6b067
:fire: Remove blank rows addition
ivov Sep 19, 2022
bd02cbf
:zap: Add more error validation
ivov Sep 19, 2022
7c61f89
:twisted_rightwards_arrows: Merge master
ivov Sep 19, 2022
c894afd
:package: Update `package-lock.json`
ivov Sep 19, 2022
33dd437
:zap: Make date logging consistent
ivov Sep 20, 2022
841d64d
:wrench: Adjust linting highlight range
ivov Sep 20, 2022
9eaf13f
:zap: Add line numbers to each item mode errors
ivov Sep 20, 2022
af1cacf
:zap: Allow for links in error descriptions
ivov Sep 20, 2022
37bd909
:zap: More input validation
ivov Sep 20, 2022
6e34ef7
:zap: Expand linting to loops
ivov Sep 20, 2022
e86e4f6
:zap: Deprecate Function and Function Item nodes
ivov Sep 20, 2022
97f449e
:twisted_rightwards_arrows: Merge master
ivov Sep 21, 2022
c7e3102
:bug: Fix placeholder syntax
ivov Sep 21, 2022
de5882d
:blue_book: Narrow down type
ivov Sep 21, 2022
3019e47
:truck: Rename using kebab-case
ivov Sep 21, 2022
0ac92e0
:fire: Remove `mapGetters`
ivov Sep 21, 2022
38721c7
:pencil2: Fix casing
ivov Sep 21, 2022
f233634
:zap: Adjust import for type
ivov Sep 21, 2022
efa7cf0
:pencil2: Fix quotes
ivov Sep 21, 2022
f833412
:bug: Fix `activeNode` reference
ivov Sep 21, 2022
9994e41
:zap: Use constant
ivov Sep 21, 2022
1f00bbb
:fire: Remove logging
ivov Sep 21, 2022
5d6bd56
:pencil2: Fix typo
ivov Sep 21, 2022
00db128
:zap: Add missing `notice`
ivov Sep 21, 2022
75927b2
:pencil2: Add tags
ivov Sep 21, 2022
29f4770
:pencil2: Fix alias
ivov Sep 22, 2022
2e48c46
:pencil2: Update copy
ivov Sep 22, 2022
2e3d429
:fire: Remove wrong linting
ivov Sep 22, 2022
0931bdc
:pencil2: Update copy
ivov Sep 22, 2022
408677b
:zap: Add validation for `null`
ivov Sep 22, 2022
c0c1fb0
:zap: Add validation for non-object and non-array
ivov Sep 22, 2022
8015b8d
:zap: Add validation for non-array with json
ivov Sep 22, 2022
0c7e101
:pencil2: Intentionally use wrong spelling
ivov Sep 22, 2022
34a167e
:zap: More validation
ivov Sep 22, 2022
dae417b
:pencil2: More copy updates
ivov Sep 22, 2022
5e5aa15
:pencil2: Placeholder updates
ivov Sep 22, 2022
00b283a
:rewind: Restore spelling
ivov Sep 22, 2022
87a5378
:zap: Fix var name
ivov Sep 22, 2022
9cd1811
:pencil2: More copy updates
ivov Sep 22, 2022
fd93630
:zap: Add luxon autocompletions
ivov Sep 22, 2022
c404699
:zap: Make scrollable
ivov Sep 22, 2022
3b70aa7
:twisted_rightwards_arrows: Merge master
ivov Sep 22, 2022
3234823
:zap: Fix comma from merge conflict resolution
ivov Sep 22, 2022
fe0e206
:package: Update `package-lock.json`
ivov Sep 22, 2022
45e43d1
:shirt: Fix lint detail
ivov Sep 22, 2022
8c24967
:art: Set font family
ivov Sep 22, 2022
3b845be
:zap: Bring in expressions fix
ivov Sep 22, 2022
e1cdd7d
:twisted_rightwards_arrows: Merge master
ivov Sep 24, 2022
92d6886
:recycle: Address feedback
ivov Sep 26, 2022
fefbfb0
:twisted_rightwards_arrows: Merge master (Vite)
ivov Sep 26, 2022
a62b8c2
:zap: Exclude codemirror packages from render chunks
ivov Sep 26, 2022
9631fc3
:bug: Fix placeholder not showing on first load
ivov Sep 26, 2022
55ef5b4
feat(editor-ui): Replace `lezer` with `esprima` in client linter (#4192)
ivov Sep 26, 2022
128a601
:zap: Match whitespace
ivov Sep 26, 2022
2cc494b
:bug: Fix selection
ivov Sep 27, 2022
3033223
:zap: Expand validation
ivov Sep 27, 2022
50a15e8
:fire: Remove validation
ivov Sep 27, 2022
fa9dd42
:pencil2: Update copy
ivov Sep 27, 2022
48567a9
:truck: Move to constants
ivov Sep 27, 2022
d9b42b8
:zap: More `null` validation
ivov Sep 27, 2022
4a7cec7
:zap: Support `all()` with index to access item
ivov Sep 27, 2022
df68964
:zap: Gloss over n8n syntax error
ivov Sep 27, 2022
ed531eb
:art: Re-style diagnostic button
ivov Sep 27, 2022
31e4c03
:fire: Remove `item` as `itemAlias`
ivov Sep 27, 2022
363e8df
:zap: Add linting for `item.json` in single item mode
ivov Sep 27, 2022
accf483
:zap: Refactor to add label info descriptions
ivov Sep 27, 2022
a6c06dc
:zap: More autocompletions
ivov Sep 27, 2022
d1982c6
:shirt: Fix lint
ivov Sep 27, 2022
6bb0c67
:zap: Simplify typings
ivov Sep 27, 2022
63f9594
feat(nodes-base): Multiline autocompletion for `code-node-editor` (#4…
ivov Sep 30, 2022
983f09b
:twisted_rightwards_arrows: Merge master
ivov Sep 30, 2022
f1ecafc
:twisted_rightwards_arrows: Merge master again
ivov Sep 30, 2022
6684045
:package: Update `package-lock.json`
ivov Sep 30, 2022
00f0c66
:shirt: Fix lint
ivov Sep 30, 2022
8c6256a
:bug: Rely on original value for custom matcher
ivov Sep 30, 2022
c06fa88
:zap: Create `customMatcherJsonFieldCompletions` to simplify setup
ivov Sep 30, 2022
e456fff
:bug: Include selector in `customMatcherJsonField` completions
ivov Sep 30, 2022
525af94
:pencil2: Make naming consistent
ivov Sep 30, 2022
e1585ae
:pencil2: Add docline
ivov Sep 30, 2022
cb688e1
:zap: Finish self-review cleanup
ivov Oct 4, 2022
5898030
:fire: Remove outdated comment
ivov Oct 4, 2022
239d791
:pushpin: Pin luxon to major-minor
ivov Oct 4, 2022
da6b857
:pencil2: Fix typo
ivov Oct 4, 2022
3d20450
:package: Update `package-lock.json`
ivov Oct 5, 2022
5e66bcd
Merge branch 'master' into n8n-4390-create-code-node
ivov Oct 5, 2022
4c5edf7
:package: Update `package-lock.json`
ivov Oct 5, 2022
fb1ab7b
:package: Re-update `package-lock.json`
ivov Oct 5, 2022
c73926e
:heavy_plus_sign: Add `luxon` for Gmail node
ivov Oct 5, 2022
53fd6e9
:package: Update `package-lock.json`
ivov Oct 5, 2022
4e388bf
:zap: Replace Function with Code in suggested nodes
ivov Oct 5, 2022
c2dab13
:bug: Fix `$prevNode` completions
ivov Oct 6, 2022
3705b8b
:pencil2: Update `$execution.mode` copy
ivov Oct 6, 2022
2eb99a3
:zap: Separate luxon getters from methods
ivov Oct 6, 2022
e063844
:zap: Adjusting linter to tolerate `.binary`
ivov Oct 6, 2022
f5f7150
:zap: Adjust top-level item keys check
ivov Oct 6, 2022
a745370
:zap: Anticipate user expecting `item` to pre-exist
ivov Oct 6, 2022
9004ca6
:zap: Add linting for legacy item access
ivov Oct 6, 2022
5b392fd
:zap: Add hint for attempted `items` access
ivov Oct 6, 2022
482a264
:zap: Add keybinding for toggling comments
ivov Oct 6, 2022
b3c8ff4
:pencil2: Update copy of `all`, `first`, `last` and `itemMatching`
ivov Oct 6, 2022
e3826c0
:bug: Make `input.all()` etc act on copies
ivov Oct 6, 2022
6a709d3
:twisted_rightwards_arrows: Merge master
ivov Oct 6, 2022
724f0e6
:package: Update `package-lock.json`
ivov Oct 6, 2022
b25bfbc
:bug: Fix guard in `$input.last()`
ivov Oct 6, 2022
caf5830
feat(Code Node): Add Python support
janober Oct 9, 2022
768fe87
:shirt: Fix lint issue
janober Oct 9, 2022
4fdc5d9
Merge branch 'master' into python-code-node
janober Oct 15, 2022
ef633d3
:package: Update `package-lock.json`
janober Oct 15, 2022
8ca2d97
:zap: Fix issue with returning proxy objects in python
janober Oct 15, 2022
8541df3
:zap: Go with default overwrite after all to cover more cases
janober Oct 15, 2022
e9cf5ff
Merge branch 'master' into python-code-node
janober Oct 22, 2022
8172e33
Merge branch 'master' into python-code-node
janober Nov 5, 2022
85a0377
Merge branch 'master' into python-code-node
janober Dec 6, 2022
a861a4e
Merge branch 'master' into python-code-node
janober Dec 7, 2022
2239fce
Update pnpm-lock file
janober Dec 7, 2022
2776439
:zap: Fix to make it work with recent changes
janober Dec 8, 2022
791545b
:zap: Make some more methods work
janober Dec 9, 2022
bce6617
Merge branch 'master' into python-code-node
janober Dec 16, 2022
2c8801f
Merge branch 'master' into python-code-node
janober Dec 26, 2022
b734457
lazy load pythonia
netroy Dec 27, 2022
255a93f
Merge remote-tracking branch 'origin/master' into python-code-node
netroy Jan 12, 2023
beea212
Merge branch 'master' into python-code-node
janober Feb 1, 2023
0519ff8
Fix lint issue
janober Feb 1, 2023
bc01a15
:zap: Replace pythonia with pyodide
janober Feb 2, 2023
93d3144
:zap: Add support for print to browser console
janober Feb 2, 2023
ab7d0bd
:zap: Add basic python support to frontend
janober Feb 2, 2023
6d3b2ba
:zap: Improvements and code cleanup
janober Feb 2, 2023
c6e5d1a
:zap: Suppress warnings
janober Feb 3, 2023
9c8ec5f
Merge branch 'master' into python-code-node
janober Feb 3, 2023
d189a2f
:zap: Fix issue with not being able to access keys with spaces
janober Feb 3, 2023
8f92b61
:zap: Adjust description
janober Feb 3, 2023
5ea20c4
:zap: Rename file to be consistent
janober Feb 3, 2023
bfabe4a
:zap: Improve error display
janober Feb 3, 2023
84e3323
:zap: Update with improved version of object conversion code
janober Feb 3, 2023
9bb59aa
:zap: Fix MaxListenersExceededWarning issue and improve performance
janober Feb 3, 2023
e56b1d3
:zap: Make sure executions are isolated
janober Feb 3, 2023
3d69d5c
:zap: Add missing file
janober Feb 3, 2023
dd15d02
Merge branch 'master' into python-code-node
janober Feb 6, 2023
61e5648
:zap: Make main function async to allow await calls inside
janober Feb 7, 2023
f84fac7
:zap: Make it possible to load modules
janober Feb 7, 2023
d7566a0
Merge branch 'master' into python-code-node
janober Feb 10, 2023
48e9722
Merge branch 'master' into python-code-node
janober Feb 26, 2023
753b9d7
:zap: Disable Python by default
janober Feb 26, 2023
17f05fa
Merge branch 'master' into python-code-node
janober Mar 6, 2023
669ad05
reset and rebuild the lockfile
netroy Mar 6, 2023
63945be
Merge branch 'master' into python-code-node
janober Mar 8, 2023
54d2d47
:zap: Fix tests
janober Mar 8, 2023
87dac07
refactor(editor): Remove monaco editor (#5446)
janober Mar 8, 2023
2d2a3c2
Add python tests
janober Mar 8, 2023
72cbbb3
Throw workflow errors in tests for easier debugging and to surface all
janober Mar 8, 2023
355923d
Merge branch 'master' into python-code-node
janober Mar 14, 2023
0357531
reset and rebuild the lockfile
netroy Mar 14, 2023
b87c727
use `map` instead of `forEach` and `push`
netroy Mar 16, 2023
f1535ac
create an error type for Pyodide
netroy Mar 16, 2023
5a7db99
remove unused workflowMode
netroy Mar 16, 2023
8fb30c0
restructure code
netroy Mar 16, 2023
6e77d56
Merge remote-tracking branch 'upstream/master' into python-code-node
netroy Mar 16, 2023
6036257
fix a typo
netroy Mar 16, 2023
35fda9d
attempt to fix the code node tests
netroy Mar 16, 2023
f924497
make SandboxPython a bit more consistent with SandboxJavaScript
netroy Mar 16, 2023
eb87618
delete redundant code in SandboxJavaScript
netroy Mar 16, 2023
82e4ff4
Merge remote-tracking branch 'upstream/master' into python-code-node
netroy Mar 17, 2023
8dcfbe8
:zap: Change test to not use subworkflow
janober Mar 18, 2023
5886f1b
:zap: Remove redundant code and normalize
janober Mar 19, 2023
2f65c14
Merge remote-tracking branch 'upstream/master' into python-code-node
netroy Mar 21, 2023
62eba41
Merge remote-tracking branch 'upstream/master' into python-code-node
netroy Mar 30, 2023
06f7c26
Merge remote-tracking branch 'upstream/master' into python-code-node
netroy Mar 30, 2023
73948d4
revert WorkflowDataProxy
netroy Mar 30, 2023
06b89cf
update @codemirror/lang-python
netroy Mar 30, 2023
d74e8ab
Merge remote-tracking branch 'origin/master' into python-code-node
netroy Apr 14, 2023
b5007cc
Merge remote-tracking branch 'origin/master' into python-code-node
netroy Apr 14, 2023
729378f
Merge remote-tracking branch 'origin/master' into python-code-node
netroy Apr 18, 2023
4520b28
Merge remote-tracking branch 'origin/master' into python-code-node
netroy Apr 26, 2023
fe10294
Merge remote-tracking branch 'origin/master' into python-code-node
netroy May 2, 2023
cf8b461
make it all work again
netroy May 2, 2023
832a65b
delete python code tests until we figure out how to load pyodide insi…
netroy May 3, 2023
0eb819e
update lockfile
netroy May 3, 2023
d567803
revert changes to auto-completions code
netroy May 3, 2023
c77b4b2
fix linting error
netroy May 3, 2023
32e43ba
make auto-completion work with python
netroy May 3, 2023
cf71f83
Merge remote-tracking branch 'origin/master' into python-code-node
netroy May 3, 2023
c9d05e2
p
netroy May 3, 2023
5a772d4
Merge remote-tracking branch 'origin/master' into python-code-node
netroy May 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/editor-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@codemirror/commands": "^6.1.0",
"@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-python": "^6.1.2",
"@codemirror/lang-sql": "^6.4.1",
"@codemirror/language": "^6.2.1",
"@codemirror/lint": "^6.0.0",
Expand Down
78 changes: 43 additions & 35 deletions packages/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
:class="['code-node-editor', $style['code-node-editor-container']]"
:class="['code-node-editor', $style['code-node-editor-container'], language]"
@mouseover="onMouseOver"
@mouseout="onMouseOut"
ref="codeNodeEditorContainer"
Expand All @@ -23,50 +23,42 @@ import type { PropType } from 'vue';
import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';

import type { LanguageSupport } from '@codemirror/language';
import type { Extension } from '@codemirror/state';
import { Compartment, EditorState } from '@codemirror/state';
import type { ViewUpdate } from '@codemirror/view';
import { EditorView } from '@codemirror/view';
import { javascript } from '@codemirror/lang-javascript';
import { json } from '@codemirror/lang-json';
import { python } from '@codemirror/lang-python';
import type { CodeExecutionMode, CodeNodeEditorLanguage } from 'n8n-workflow';
import { CODE_EXECUTION_MODES, CODE_LANGUAGES } from 'n8n-workflow';

import { readOnlyEditorExtensions, writableEditorExtensions } from './baseExtensions';
import { linterExtension } from './linter';
import { completerExtension } from './completer';
import { codeNodeEditorTheme } from './theme';
import { workflowHelpers } from '@/mixins/workflowHelpers'; // for json field completions
import { ASK_AI_MODAL_KEY, CODE_NODE_TYPE } from '@/constants';
import { codeNodeEditorEventBus } from '@/event-bus';
import {
ALL_ITEMS_PLACEHOLDER,
CODE_LANGUAGES,
CODE_MODES,
EACH_ITEM_PLACEHOLDER,
} from './constants';
import { useRootStore } from '@/stores/n8nRootStore';
import Modal from '../Modal.vue';
import { useSettingsStore } from '@/stores/settings';
import type { CodeLanguage, CodeMode } from './types';
import Modal from '@/components/Modal.vue';

const placeholders: Partial<Record<CodeLanguage, Record<CodeMode, string>>> = {
javaScript: {
runOnceForAllItems: ALL_ITEMS_PLACEHOLDER,
runOnceForEachItem: EACH_ITEM_PLACEHOLDER,
},
};
import { readOnlyEditorExtensions, writableEditorExtensions } from './baseExtensions';
import { CODE_PLACEHOLDERS } from './constants';
import { linterExtension } from './linter';
import { completerExtension } from './completer';
import { codeNodeEditorTheme } from './theme';

export default mixins(linterExtension, completerExtension, workflowHelpers).extend({
name: 'code-node-editor',
components: { Modal },
props: {
mode: {
type: String as PropType<CodeMode>,
validator: (value: CodeMode): boolean => CODE_MODES.includes(value),
type: String as PropType<CodeExecutionMode>,
validator: (value: CodeExecutionMode): boolean => CODE_EXECUTION_MODES.includes(value),
},
language: {
type: String as PropType<CodeLanguage>,
default: 'javaScript' as CodeLanguage,
validator: (value: CodeLanguage): boolean => CODE_LANGUAGES.includes(value),
type: String as PropType<CodeNodeEditorLanguage>,
default: 'javaScript' as CodeNodeEditorLanguage,
validator: (value: CodeNodeEditorLanguage): boolean => CODE_LANGUAGES.includes(value),
},
isReadOnly: {
type: Boolean,
Expand All @@ -79,19 +71,30 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
data() {
return {
editor: null as EditorView | null,
languageCompartment: new Compartment(),
linterCompartment: new Compartment(),
isEditorHovered: false,
isEditorFocused: false,
};
},
watch: {
mode(newMode, previousMode: CodeMode) {
mode(newMode, previousMode: CodeExecutionMode) {
this.reloadLinter();

if (this.content.trim() === placeholders[this.language]?.[previousMode]) {
if (this.content.trim() === CODE_PLACEHOLDERS[this.language]?.[previousMode]) {
this.refreshPlaceholder();
}
},
language(newLanguage, previousLanguage: CodeNodeEditorLanguage) {
if (this.content.trim() === CODE_PLACEHOLDERS[previousLanguage]?.[this.mode]) {
this.refreshPlaceholder();
}

const [languageSupport] = this.languageExtensions;
this.editor?.dispatch({
effects: this.languageCompartment.reconfigure(languageSupport),
});
},
},
computed: {
...mapStores(useRootStore),
Expand All @@ -104,7 +107,17 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
return this.editor.state.doc.toString();
},
placeholder(): string {
return placeholders[this.language]?.[this.mode] ?? '';
return CODE_PLACEHOLDERS[this.language]?.[this.mode] ?? '';
},
languageExtensions(): [LanguageSupport, ...Extension[]] {
switch (this.language) {
case 'json':
return [json()];
case 'javaScript':
return [javascript(), this.autocompletionExtension('javaScript')];
case 'python':
return [python(), this.autocompletionExtension('python')];
}
},
},
methods: {
Expand Down Expand Up @@ -178,6 +191,7 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
insertedText = full.slice(lastDotIndex + 1);
}

// TODO: Still has to get updated for Python and JSON
this.$telemetry.track('User autocompleted code', {
instance_id: this.rootStore.instanceId,
node_type: CODE_NODE_TYPE,
Expand Down Expand Up @@ -234,14 +248,8 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
);
}

switch (language) {
case 'json':
extensions.push(json());
break;
case 'javaScript':
extensions.push(javascript(), this.autocompletionExtension());
break;
}
const [languageSupport, ...otherExtensions] = this.languageExtensions;
extensions.push(this.languageCompartment.of(languageSupport), ...otherExtensions);

const state = EditorState.create({
doc: this.value || this.placeholder,
Expand Down
10 changes: 7 additions & 3 deletions packages/editor-ui/src/components/CodeNodeEditor/completer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,20 @@ export const completerExtension = mixins(
jsonFieldCompletions,
).extend({
methods: {
autocompletionExtension(): Extension {
autocompletionExtension(language: 'javaScript' | 'python'): Extension {
const completions = [];
if (language === 'javaScript') {
completions.push(jsSnippets, localCompletionSource);
}

return autocompletion({
compareCompletions: (a: Completion, b: Completion) => {
if (/\.json$|id$|id['"]\]$/.test(a.label)) return 0;

return a.label.localeCompare(b.label);
},
override: [
jsSnippets,
localCompletionSource,
...completions,

// core
this.itemCompletions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { CodeNodeEditorMixin } from '../types';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows';

function getAutocompletableNodeNames(nodes: INodeUi[]) {
function getAutoCompletableNodeNames(nodes: INodeUi[]) {
return nodes
.filter((node: INodeUi) => !NODE_TYPES_EXCLUDED_FROM_AUTOCOMPLETION.includes(node.type))
.map((node: INodeUi) => node.name);
Expand Down Expand Up @@ -49,64 +49,65 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
* - Complete `$` to `$json $binary $itemIndex` in single-item mode.
*/
baseCompletions(context: CompletionContext): CompletionResult | null {
const preCursor = context.matchBefore(/\$\w*/);
const prefix = this.language === 'python' ? '_' : '$';
const preCursor = context.matchBefore(new RegExp(`\\${prefix}\\w*`));

if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;

const TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES: Completion[] = [
{
label: '$execution',
label: `${prefix}execution`,
info: this.$locale.baseText('codeNodeEditor.completer.$execution'),
},
{ label: '$input', info: this.$locale.baseText('codeNodeEditor.completer.$input') },
{ label: `${prefix}input`, info: this.$locale.baseText('codeNodeEditor.completer.$input') },
{
label: '$prevNode',
label: `${prefix}prevNode`,
info: this.$locale.baseText('codeNodeEditor.completer.$prevNode'),
},
{
label: '$workflow',
label: `${prefix}workflow`,
info: this.$locale.baseText('codeNodeEditor.completer.$workflow'),
},
{
label: '$vars',
label: `${prefix}vars`,
info: this.$locale.baseText('codeNodeEditor.completer.$vars'),
},
{
label: '$now',
label: `${prefix}now`,
info: this.$locale.baseText('codeNodeEditor.completer.$now'),
},
{
label: '$today',
label: `${prefix}today`,
info: this.$locale.baseText('codeNodeEditor.completer.$today'),
},
{
label: '$jmespath()',
label: `${prefix}jmespath()`,
info: this.$locale.baseText('codeNodeEditor.completer.$jmespath'),
},
{
label: '$if()',
label: `${prefix}if()`,
info: this.$locale.baseText('codeNodeEditor.completer.$if'),
},
{
label: '$min()',
label: `${prefix}min()`,
info: this.$locale.baseText('codeNodeEditor.completer.$min'),
},
{
label: '$max()',
label: `${prefix}max()`,
info: this.$locale.baseText('codeNodeEditor.completer.$max'),
},
{
label: '$runIndex',
label: `${prefix}runIndex`,
info: this.$locale.baseText('codeNodeEditor.completer.$runIndex'),
},
];

const options: Completion[] = TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES.map(addVarType);

options.push(
...getAutocompletableNodeNames(this.workflowsStore.allNodes).map((nodeName) => {
...getAutoCompletableNodeNames(this.workflowsStore.allNodes).map((nodeName) => {
return {
label: `$('${nodeName}')`,
label: `${prefix}('${nodeName}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
Expand All @@ -117,10 +118,10 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({

if (this.mode === 'runOnceForEachItem') {
const TOP_LEVEL_COMPLETIONS_IN_SINGLE_ITEM_MODE = [
{ label: '$json' },
{ label: '$binary' },
{ label: `${prefix}json` },
{ label: `${prefix}binary` },
{
label: '$itemIndex',
label: `${prefix}itemIndex`,
info: this.$locale.baseText('codeNodeEditor.completer.$itemIndex'),
},
];
Expand All @@ -138,14 +139,15 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
* Complete `$(` to `$('nodeName')`.
*/
nodeSelectorCompletions(context: CompletionContext): CompletionResult | null {
const preCursor = context.matchBefore(/\$\(.*/);
const prefix = this.language === 'python' ? '_' : '$';
const preCursor = context.matchBefore(new RegExp(`\\${prefix}\\(.*`));

if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;

const options: Completion[] = getAutocompletableNodeNames(this.workflowsStore.allNodes).map(
const options: Completion[] = getAutoCompletableNodeNames(this.workflowsStore.allNodes).map(
(nodeName) => {
return {
label: `$('${nodeName}')`,
label: `${prefix}('${nodeName}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ export const itemFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
* - Complete `$input.item.` to `.json .binary`.
*/
inputMethodCompletions(context: CompletionContext): CompletionResult | null {
const prefix = this.language === 'python' ? '_' : '$';
const patterns = {
first: /\$input\.first\(\)\..*/,
last: /\$input\.last\(\)\..*/,
item: /\$input\.item\..*/,
first: new RegExp(`\\${prefix}input\\.first\\(\\)\\..*`),
last: new RegExp(`\\${prefix}input\\.last\\(\\)\\..*`),
item: new RegExp(`\\${prefix}item\\.first\\(\\)\\..*`),
all: /\$input\.all\(\)\[(?<index>\w+)\]\..*/,
};

Expand All @@ -64,11 +65,11 @@ export const itemFieldCompletions = (Vue as CodeNodeEditorMixin).extend({

let replacementBase = '';

if (name === 'item') replacementBase = '$input.item';
if (name === 'item') replacementBase = `${prefix}input.item`;

if (name === 'first') replacementBase = '$input.first()';
if (name === 'first') replacementBase = `${prefix}input.first()`;

if (name === 'last') replacementBase = '$input.last()';
if (name === 'last') replacementBase = `${prefix}input.last()`;

if (name === 'all') {
const match = preCursor.text.match(regex);
Expand All @@ -77,7 +78,7 @@ export const itemFieldCompletions = (Vue as CodeNodeEditorMixin).extend({

const { index } = match.groups;

replacementBase = `$input.all()[${index}]`;
replacementBase = `${prefix}input.all()[${index}]`;
}

const options: Completion[] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vue from 'vue';
import { AUTOCOMPLETABLE_BUILT_IN_MODULES } from '../constants';
import { AUTOCOMPLETABLE_BUILT_IN_MODULES_JS } from '../constants';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { CodeNodeEditorMixin } from '../types';
import { useSettingsStore } from '@/stores/settings';
Expand All @@ -25,7 +25,7 @@ export const requireCompletions = (Vue as CodeNodeEditorMixin).extend({

if (allowedModules.builtIn) {
if (allowedModules.builtIn.includes('*')) {
options.push(...AUTOCOMPLETABLE_BUILT_IN_MODULES.map(toOption));
options.push(...AUTOCOMPLETABLE_BUILT_IN_MODULES_JS.map(toOption));
} else if (allowedModules?.builtIn?.length > 0) {
options.push(...allowedModules.builtIn.map(toOption));
}
Expand Down
Loading