mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-29 09:00:26 -05:00
fix(core): avoid crashing UI in case of multiline function autocomplete (#11684)
This commit is contained in:
committed by
brian.mulier
parent
54482e1d06
commit
95133ebc40
@@ -1,17 +1,23 @@
|
||||
const pebbleStart = "\\{\\{ *";
|
||||
const fieldWithoutDotCapture = "([^\\(\\)}:~. ]*)(?![^\\(\\)}\\s])";
|
||||
const dotAccessedFieldWithParentCapture = "([^\\(\\)},:~ ]+)\\." + fieldWithoutDotCapture;
|
||||
const maybeTextFollowedBySeparator = "(?:[^~},: ]*[~ ]+)*";
|
||||
const maybeParams = "((?:[^\\n\\(\\)~},:= ]+=[^\\n~},:= ]+(?: *, *)?)+)?['\"]?([^\\n\\(\\)~},:= ]*)?";
|
||||
const functionWithMaybeParams = "([^\\n\\(\\)},:~ ]+)\\(" + maybeParams
|
||||
const maybeText = (allowSeparators: boolean) => "(?:\"[^\"]*\")|(?:'[^']*')|(?:(?:(?!\\}\\})" + (allowSeparators ? "[\\S\\n ]" : "[^~+,:\\n ]") + ")*)";
|
||||
const maybeAnotherPebbleExpression = "(?:[\\n ]*\\{\\{[\\n ]*" + maybeText(true) + "[\\n ]*\\}\\}[\\n ]*)*";
|
||||
const pebbleStart = "\\{\\{[\\n ]*";
|
||||
const fieldWithoutDotCapture = "([^\\(\\)\\}:~+.\\n '\"]*)(?![^\\(\\)\\}\\n ])";
|
||||
const dotAccessedFieldWithParentCapture = "([^\\(\\)\\}:~+\\n '\"]*)\\." + fieldWithoutDotCapture;
|
||||
const maybeTextFollowedBySeparator = "(?:" + maybeText(false) + "[~+ ]+)*";
|
||||
const paramKey = "[^\\n \\(\\)~+\\},:=]+";
|
||||
const paramValue = "(?:(?:(?:\"[^\"]*\"?)|(?:'[^']*'?)|[^,)]))*";
|
||||
const maybeParams = "(" +
|
||||
"(?:[\\n ]*" + paramKey + "[\\n ]*=[\\n ]*" + paramValue + "(?:[\\n ]*,[\\n ]*)?)+)?" +
|
||||
"([^\\n \\(\\)~+\\},:=]*)?";
|
||||
const functionWithMaybeParams = "([^\\n\\(\\)\\},:~ ]+)\\(" + maybeParams
|
||||
|
||||
export default {
|
||||
beforeSeparator: (additionalSeparators: string[] = []) => `([^}:\\s${additionalSeparators.join("")}]*)`,
|
||||
beforeSeparator: (additionalSeparators: string[] = []) => `([^\\}:\\n ${additionalSeparators.join("")}]*)`,
|
||||
/** [fullMatch, dotForbiddenField] */
|
||||
capturePebbleVarRoot: `${pebbleStart}${maybeTextFollowedBySeparator}${fieldWithoutDotCapture}`,
|
||||
capturePebbleVarRoot: `${maybeAnotherPebbleExpression}${pebbleStart}${maybeTextFollowedBySeparator}${fieldWithoutDotCapture}`,
|
||||
/** [fullMatch, parentFieldMaybeIncludingDots, childField] */
|
||||
capturePebbleVarParent: `${pebbleStart}${maybeTextFollowedBySeparator}${dotAccessedFieldWithParentCapture}`,
|
||||
capturePebbleVarParent: `${maybeAnotherPebbleExpression}${pebbleStart}${maybeTextFollowedBySeparator}${dotAccessedFieldWithParentCapture}`,
|
||||
/** [fullMatch, functionName, textBetweenParenthesis, maybeTypedWordStart] */
|
||||
capturePebbleFunction: `${pebbleStart}${maybeTextFollowedBySeparator}${functionWithMaybeParams}`,
|
||||
capturePebbleFunction: `${maybeAnotherPebbleExpression}${pebbleStart}${maybeTextFollowedBySeparator}${functionWithMaybeParams}`,
|
||||
captureStringValue: "^[\"']([^\"']+)[\"']$"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ describe("Regex", () => {
|
||||
|
||||
functionMatcher = new RegExp(RegexProvider.capturePebbleFunction + "$").exec("{{myFunc(my-param_1='value1', myK");
|
||||
expect([...functionMatcher]).toEqual(["{{myFunc(my-param_1='value1', myK", "myFunc", "my-param_1='value1', ", "myK"]);
|
||||
|
||||
functionMatcher = new RegExp(RegexProvider.capturePebbleFunction + "$").exec("{{myFunc(my-param_1='value1')}} {{mySecondFunc(second-func-param_1='secondFuncValue1', 'to") ?? [];
|
||||
expect([...functionMatcher]).toEqual(["{{myFunc(my-param_1='value1')}} {{mySecondFunc(second-func-param_1='secondFuncValue1', 'to", "mySecondFunc", "second-func-param_1='secondFuncValue1', ", "'to"]);
|
||||
})
|
||||
|
||||
it("capture string value", () => {
|
||||
@@ -71,4 +74,58 @@ describe("Regex", () => {
|
||||
stringMatcher = new RegExp(RegexProvider.captureStringValue).exec("a");
|
||||
expect(stringMatcher).toBeNull();
|
||||
})
|
||||
|
||||
it("multiline function, avoid crashing", () => {
|
||||
const complexMultilineFunctionButClosedPebbleExpression = `id: breaking-ui
|
||||
namespace: io.kestra.blx
|
||||
description: "Upload multiple files to s3 sequentially"
|
||||
|
||||
|
||||
tasks:
|
||||
- id: placeholder
|
||||
type: io.kestra.plugin.core.log.Log
|
||||
message: |-
|
||||
{{
|
||||
"to_entries[] | select(.key | startswith(\\"" +
|
||||
inputs.selector +
|
||||
"\\")) | (.key + \\"->\\" + .value)"
|
||||
}}
|
||||
`
|
||||
const regex = new RegExp(RegexProvider.capturePebbleFunction + "$");
|
||||
expect(regex.exec(complexMultilineFunctionButClosedPebbleExpression)).eq(null);
|
||||
|
||||
const shouldMatchLastFunction = `id: breaking-ui
|
||||
namespace: io.kestra.blx
|
||||
description: "Upload multiple files to s3 sequentially"
|
||||
|
||||
|
||||
tasks:
|
||||
- id: placeholder
|
||||
type: io.kestra.plugin.core.log.Log
|
||||
message: |-
|
||||
{{
|
||||
"to_entries[] | select(.key | startswith(\\"" +
|
||||
inputs.selector +
|
||||
"\\")) | (.key + \\"->\\" + .value)"
|
||||
}} {{myFunc(my-param_1='value1', my-param_2="value2", myK`
|
||||
expect([...(regex.exec(shouldMatchLastFunction) ?? [])]).toEqual([
|
||||
`id: breaking-ui
|
||||
namespace: io.kestra.blx
|
||||
description: "Upload multiple files to s3 sequentially"
|
||||
|
||||
|
||||
tasks:
|
||||
- id: placeholder
|
||||
type: io.kestra.plugin.core.log.Log
|
||||
message: |-
|
||||
{{
|
||||
"to_entries[] | select(.key | startswith(\\"" +
|
||||
inputs.selector +
|
||||
"\\")) | (.key + \\"->\\" + .value)"
|
||||
}} {{myFunc(my-param_1='value1', my-param_2="value2", myK`,
|
||||
"myFunc",
|
||||
"my-param_1='value1', my-param_2=\"value2\", ",
|
||||
"myK",
|
||||
]);
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user