Skip to content

Commit

Permalink
#8404: fix variable path regex to not switch to text entry mode durin…
Browse files Browse the repository at this point in the history
…g optional chaining (#8635)
  • Loading branch information
twschiller authored Jun 17, 2024
1 parent 190d724 commit c32e86f
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,17 @@ describe("TextWidget", () => {
expect(isVarValue("@example.property['nestedProperty']")).toBe(true);
expect(isVarValue('@example["property"].nestedProperty')).toBe(true);
expect(isVarValue("@example.property.nestedProperty")).toBe(true);
expect(isVarValue("@myObject.optionalProperty?.bar")).toBe(true);
expect(isVarValue("@myOptionalObject?.bar")).toBe(true);

// Invalid strings:
expect(isVarValue("abc")).toBe(false);
expect(isVarValue("@property extra text")).toBe(false);
expect(isVarValue("@123")).toBe(false);
expect(isVarValue("@")).toBe(false);
expect(isVarValue("@myObject.optionalProperty?")).toBe(false);
expect(isVarValue("?")).toBe(false);
expect(isVarValue("?@abc")).toBe(false);
});

test("isVarLike", () => {
Expand All @@ -101,6 +106,8 @@ describe("TextWidget", () => {
expect(isVarLike("@object[")).toBe(true);
expect(isVarLike("@object[0")).toBe(true);
expect(isVarLike("@object.")).toBe(true);
expect(isVarLike("@object?")).toBe(true);
expect(isVarLike("@object?.")).toBe(true);
expect(isVarLike("@obj ect.")).toBe(false);
});
});
7 changes: 5 additions & 2 deletions src/components/fields/schemaFields/widgets/TextWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ function schemaSupportsTemplates(schema: Schema): boolean {
// -@: Check for a @ character at the beginning of the string.
// -(?!\d): Ensure the first character of the identifier is not a digit.
// -([\w$]+): Capture the initial identifier, which can consist of letters, digits, underscores, or dollar signs.
// -((\.[\w$]+)|(\[(\d+|"[^"]+")\]))*: Match any number of properties or array indices, separated by periods or enclosed in square brackets.\.[\w$]+: A property preceded by a period, consisting of letters, digits, underscores, or dollar signs.
// -((\??\.[\w$]+)|(\[(\d+|"[^"]+")\]))*: Match any number of properties or array indices, separated by periods (potentially with an optional chaining question mark) or enclosed in square brackets.\.[\w$]+: A property preceded by a period, consisting of letters, digits, underscores, or dollar signs.
// -\[(\d+|"[^"]+")\]: Either an array index consisting of one or more digits, or a property name wrapped in double quotes and containing any characters except double quotes, both enclosed in square brackets.
// -$: Assert the end of the string.
const objectPathRegex =
// eslint-disable-next-line security/detect-unsafe-regex -- risky for long strings, but ok for var names
/^@(?!\d)([\w$]+)((\.[\w$]+)|(\[(\d+|"[^"]+"|'[^']+')]))*$/;
/^@(?!\d)([\w$]+)((\??\.[\w$]+)|(\[(\d+|"[^"]+"|'[^']+')]))*$/;

// Regex to help detect if the user is typing a bracket expression on the end of a variable
// eslint-disable-next-line security/detect-unsafe-regex -- risky for long strings, but ok for var names
Expand All @@ -85,6 +85,9 @@ export function isVarLike(value: string): boolean {
isVarValue(value) ||
// User-just started typing a variable
value === "@" ||
// User is starting to access an optional property
isVarValue(trimEndOnce(value, "?")) ||
isVarValue(trimEndOnce(value, "?.")) ||
// User is starting to access a sub property.
isVarValue(trimEndOnce(value, ".")) ||
// User is starting to access an array index, or property with whitespace.
Expand Down

0 comments on commit c32e86f

Please sign in to comment.