Skip to content

Commit

Permalink
fix(editor): Escape node names with quotes in autocomplete and drag'n…
Browse files Browse the repository at this point in the history
…'drop (#8663)
  • Loading branch information
elsmr authored Feb 21, 2024
1 parent c346002 commit 890c2bd
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Completion, CompletionContext, CompletionResult } from '@codemirro
import type { INodeUi } from '@/Interface';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { escapeMappingString } from '@/utils/mappingUtils';

function getAutoCompletableNodeNames(nodes: INodeUi[]) {
return nodes
Expand Down Expand Up @@ -98,7 +99,7 @@ export const baseCompletions = defineComponent({
options.push(
...getAutoCompletableNodeNames(this.workflowsStore.allNodes).map((nodeName) => {
return {
label: `${prefix}('${nodeName}')`,
label: `${prefix}('${escapeMappingString(nodeName)}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
Expand Down Expand Up @@ -138,7 +139,7 @@ export const baseCompletions = defineComponent({
const options: Completion[] = getAutoCompletableNodeNames(this.workflowsStore.allNodes).map(
(nodeName) => {
return {
label: `${prefix}('${nodeName}')`,
label: `${prefix}('${escapeMappingString(nodeName)}')`,
type: 'variable',
info: this.$locale.baseText('codeNodeEditor.completer.$()', {
interpolate: { nodeName },
Expand Down
18 changes: 14 additions & 4 deletions packages/editor-ui/src/components/VariableSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { useRootStore } from '@/stores/n8nRoot.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useRouter } from 'vue-router';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { escapeMappingString } from '@/utils/mappingUtils';
// Node types that should not be displayed in variable selector
const SKIPPED_NODE_TYPES = [STICKY_NODE_TYPE];
Expand Down Expand Up @@ -398,7 +399,9 @@ export default defineComponent({
// Get json data
if (outputData.hasOwnProperty('json')) {
const jsonPropertyPrefix = useShort ? '$json' : `$('${nodeName}').item.json`;
const jsonPropertyPrefix = useShort
? '$json'
: `$('${escapeMappingString(nodeName)}').item.json`;
const jsonDataOptions: IVariableSelectorOption[] = [];
for (const propertyName of Object.keys(outputData.json)) {
Expand All @@ -423,7 +426,9 @@ export default defineComponent({
// Get binary data
if (outputData.hasOwnProperty('binary')) {
const binaryPropertyPrefix = useShort ? '$binary' : `$('${nodeName}').item.binary`;
const binaryPropertyPrefix = useShort
? '$binary'
: `$('${escapeMappingString(nodeName)}').item.binary`;
const binaryData = [];
let binaryPropertyData = [];
Expand Down Expand Up @@ -537,7 +542,7 @@ export default defineComponent({
returnData.push({
name: key,
key: `$('${nodeName}').context["${key}"]`,
key: `$('${escapeMappingString(nodeName)}').context['${escapeMappingString(key)}']`,
// @ts-ignore
value: nodeContext[key],
});
Expand Down Expand Up @@ -793,7 +798,12 @@ export default defineComponent({
{
name: this.$locale.baseText('variableSelector.parameters'),
options: this.sortOptions(
this.getNodeParameters(nodeName, `$('${nodeName}').params`, undefined, filterText),
this.getNodeParameters(
nodeName,
`$('${escapeMappingString(nodeName)}').params`,
undefined,
filterText,
),
),
} as IVariableSelectorOption,
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from './utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { useExternalSecretsStore } from '@/stores/externalSecrets.ee.store';
import { escapeMappingString } from '@/utils/mappingUtils';

/**
* Completions offered at the dollar position: `$|`
Expand Down Expand Up @@ -90,7 +91,7 @@ export function dollarOptions() {
})
.concat(
autocompletableNodeNames().map((nodeName) => ({
label: `$('${nodeName}')`,
label: `$('${escapeMappingString(nodeName)}')`,
type: 'keyword',
info: i18n.baseText('codeNodeEditor.completer.$()', { interpolate: { nodeName } }),
})),
Expand Down
10 changes: 9 additions & 1 deletion packages/editor-ui/src/utils/__tests__/mappingUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { INodeProperties } from 'n8n-workflow';
import { getMappedResult, getMappedExpression } from '../mappingUtils';
import { getMappedResult, getMappedExpression, escapeMappingString } from '../mappingUtils';

const RLC_PARAM: INodeProperties = {
displayName: 'Base',
Expand Down Expand Up @@ -273,4 +273,12 @@ describe('Mapping Utils', () => {
);
});
});
describe('escapeMappingString', () => {
test.each([
{ input: 'Normal node name (here)', output: 'Normal node name (here)' },
{ input: "'Should es'ape quotes here'", output: "\\'Should es\\'ape quotes here\\'" },
])('should escape "$input" to "$output"', ({ input, output }) => {
expect(escapeMappingString(input)).toEqual(output);
});
});
});
8 changes: 7 additions & 1 deletion packages/editor-ui/src/utils/mappingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export function generatePath(root: string, path: Array<string | number>): string
}, root);
}

export function escapeMappingString(str: string): string {
return str.replace(/\'/g, "\\'");
}

export function getMappedExpression({
nodeName,
distanceFromActive,
Expand All @@ -28,7 +32,9 @@ export function getMappedExpression({
path: Array<string | number> | string;
}) {
const root =
distanceFromActive === 1 ? '$json' : generatePath(`$('${nodeName}')`, ['item', 'json']);
distanceFromActive === 1
? '$json'
: generatePath(`$('${escapeMappingString(nodeName)}')`, ['item', 'json']);

if (typeof path === 'string') {
return `{{ ${root}${path} }}`;
Expand Down

0 comments on commit 890c2bd

Please sign in to comment.