diff --git a/packages/builder/src/builderStore/componentUtils.js b/packages/builder/src/builderStore/componentUtils.js index 2ad7e82075..ca9d5332bb 100644 --- a/packages/builder/src/builderStore/componentUtils.js +++ b/packages/builder/src/builderStore/componentUtils.js @@ -182,43 +182,42 @@ export const makeComponentUnique = component => { // Replace component ID const oldId = component._id const newId = Helpers.uuid() - component._id = newId + let definition = JSON.stringify(component) - if (component._children?.length) { - let children = JSON.stringify(component._children) + // Replace all instances of this ID in HBS bindings + definition = definition.replace(new RegExp(oldId, "g"), newId) - // Replace all instances of this ID in child HBS bindings - children = children.replace(new RegExp(oldId, "g"), newId) + // Replace all instances of this ID in JS bindings + const bindings = findHBSBlocks(definition) + bindings.forEach(binding => { + // JSON.stringify will have escaped double quotes, so we need + // to account for that + let sanitizedBinding = binding.replace(/\\"/g, '"') - // Replace all instances of this ID in child JS bindings - const bindings = findHBSBlocks(children) - bindings.forEach(binding => { - // JSON.stringify will have escaped double quotes, so we need - // to account for that - let sanitizedBinding = binding.replace(/\\"/g, '"') + // Check if this is a valid JS binding + let js = decodeJSBinding(sanitizedBinding) + if (js != null) { + // Replace ID inside JS binding + js = js.replace(new RegExp(oldId, "g"), newId) - // Check if this is a valid JS binding - let js = decodeJSBinding(sanitizedBinding) - if (js != null) { - // Replace ID inside JS binding - js = js.replace(new RegExp(oldId, "g"), newId) + // Create new valid JS binding + let newBinding = encodeJSBinding(js) - // Create new valid JS binding - let newBinding = encodeJSBinding(js) + // Replace escaped double quotes + newBinding = newBinding.replace(/"/g, '\\"') - // Replace escaped double quotes - newBinding = newBinding.replace(/"/g, '\\"') + // Insert new JS back into binding. + // A single string replace here is better than a regex as + // the binding contains special characters, and we only need + // to replace a single instance. + definition = definition.replace(binding, newBinding) + } + }) - // Insert new JS back into binding. - // A single string replace here is better than a regex as - // the binding contains special characters, and we only need - // to replace a single instance. - children = children.replace(binding, newBinding) - } - }) - - // Recurse on all children - component._children = JSON.parse(children) - component._children.forEach(makeComponentUnique) + // Recurse on all children + component = JSON.parse(definition) + return { + ...component, + _children: component._children?.map(makeComponentUnique), } } diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 933695d0ec..c05427ed4f 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -595,7 +595,7 @@ export const getFrontendStore = () => { // Make new component unique if copying if (!cut) { - makeComponentUnique(componentToPaste) + componentToPaste = makeComponentUnique(componentToPaste) } newComponentId = componentToPaste._id @@ -905,7 +905,7 @@ export const getFrontendStore = () => { } // Replace block with ejected definition - makeComponentUnique(ejectedDefinition) + ejectedDefinition = makeComponentUnique(ejectedDefinition) const index = parent._children.findIndex(x => x._id === componentId) parent._children[index] = ejectedDefinition nextSelectedComponentId = ejectedDefinition._id diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenDropdownMenu.svelte index 0c35fa391e..ec965ed659 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenDropdownMenu.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenDropdownMenu.svelte @@ -38,7 +38,7 @@ let duplicateScreen = Helpers.cloneDeep(screen) delete duplicateScreen._id delete duplicateScreen._rev - makeComponentUnique(duplicateScreen.props) + duplicateScreen.props = makeComponentUnique(duplicateScreen.props) // Attach the new name and URL duplicateScreen.routing.route = sanitizeUrl(screenUrl)