Fix data binding replacing partial matches
This commit is contained in:
parent
67786ea58a
commit
c9cf9ad506
|
@ -1317,6 +1317,22 @@ const shouldReplaceBinding = (currentValue, from, convertTo, binding) => {
|
|||
return !invalids.find(invalid => noSpaces?.includes(invalid))
|
||||
}
|
||||
|
||||
// If converting readable to runtime we need to ensure we don't replace words
|
||||
// which are substrings of other words - e.g. a binding of `a` would turn
|
||||
// `hah` into `h[a]h` which is obviously wrong. To avoid this we can strip all
|
||||
// expanded versions of the binding, then ensure the binding still exists.
|
||||
const excludeExtensions = (string, binding) => {
|
||||
// Regex to find prefixed bindings (e.g. exclude xfoo for foo)
|
||||
const regex1 = new RegExp(`[a-zA-Z0-9-_]+${binding}[a-zA-Z0-9-_]*`, "g")
|
||||
// Regex to find prefixed bindings (e.g. exclude foox for foo)
|
||||
const regex2 = new RegExp(`[a-zA-Z0-9-_]*${binding}[a-zA-Z0-9-_]+`, "g")
|
||||
const matches = [...string.matchAll(regex1), ...string.matchAll(regex2)]
|
||||
for (let match of matches) {
|
||||
string = string.replace(match[0], new Array(match[0].length + 1).join("*"))
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function which replaces a string between given indices.
|
||||
*/
|
||||
|
@ -1361,6 +1377,10 @@ const bindingReplacement = (
|
|||
// in the search, working from longest to shortest so always use best match first
|
||||
let searchString = newBoundValue
|
||||
for (let from of convertFromProps) {
|
||||
// Blank out all extensions of this string to avoid partial matches
|
||||
if (convertTo === "runtimeBinding") {
|
||||
searchString = excludeExtensions(searchString, from)
|
||||
}
|
||||
const binding = bindableProperties.find(el => el[convertFrom] === from)
|
||||
if (
|
||||
isJS ||
|
||||
|
|
|
@ -72,6 +72,13 @@ describe("Builder dataBinding", () => {
|
|||
runtimeBinding: "count",
|
||||
type: "context",
|
||||
},
|
||||
{
|
||||
category: "Bindings",
|
||||
icon: "Brackets",
|
||||
readableBinding: "location",
|
||||
runtimeBinding: "[location]",
|
||||
type: "context",
|
||||
},
|
||||
]
|
||||
it("should convert a readable binding to a runtime one", () => {
|
||||
const textWithBindings = `Hello {{ Current User.firstName }}! The count is {{ Binding.count }}.`
|
||||
|
@ -83,6 +90,18 @@ describe("Builder dataBinding", () => {
|
|||
)
|
||||
).toEqual(`Hello {{ [user].[firstName] }}! The count is {{ count }}.`)
|
||||
})
|
||||
it("should not convert a partial match", () => {
|
||||
const textWithBindings = `location {{ _location Zlocation location locationZ _location_ }}`
|
||||
expect(
|
||||
readableToRuntimeBinding(
|
||||
bindableProperties,
|
||||
textWithBindings,
|
||||
"runtimeBinding"
|
||||
)
|
||||
).toEqual(
|
||||
`location {{ _location Zlocation [location] locationZ _location_ }}`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("updateReferencesInObject", () => {
|
||||
|
|
Loading…
Reference in New Issue