From b19b9de00b0876a8509b9b518fe203065c512b35 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Thu, 12 Sep 2024 10:15:51 -0700 Subject: [PATCH] patch projects with top-level shadow blocks --- pxtblocks/importer.ts | 80 +++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/pxtblocks/importer.ts b/pxtblocks/importer.ts index 41d83a3f7e3..d7db241d2e4 100644 --- a/pxtblocks/importer.ts +++ b/pxtblocks/importer.ts @@ -382,6 +382,14 @@ function promoteShadow(shadow: Element) { shadow.remove(); return undefined; } + const newBlock = createBlockFromShadow(shadow); + shadow.parentElement.appendChild(newBlock); + shadow.remove(); + + return newBlock; +}; + +function createBlockFromShadow(shadow: Element) { const newBlock = Blockly.utils.xml.createElement("block"); for (const attr of shadow.getAttributeNames()) { @@ -392,45 +400,59 @@ function promoteShadow(shadow: Element) { newBlock.appendChild(child.cloneNode(true)); } - shadow.parentElement.appendChild(newBlock); - shadow.remove(); - return newBlock; -}; +} export function patchShadows(root: Element, inShadow: boolean) { if (root.tagName === "shadow") { - const type = root.getAttribute("type"); - let shouldPatch = false; - - switch (type) { - case "variables_get_reporter": - case "argument_reporter_boolean": - case "argument_reporter_number": - case "argument_reporter_string": - case "argument_reporter_array": - case "argument_reporter_custom": - shouldPatch = true; - break; + if (root.parentElement?.tagName === "xml") { + console.warn(`Shadow block of type '${root.getAttribute("type")}' found at top level. Converting to non-shadow block`); + pxt.tickEvent(`blocks.import.topLevelShadow`, { blockId: root.getAttribute("type") }); + + const newBlock = createBlockFromShadow(root); + root.parentElement.insertBefore(newBlock, root); + root.remove(); + root = newBlock; + + const mutation = getDirectChildren(root, "mutation")[0]; + if (mutation?.hasAttribute("dupliacteondrag")) { + mutation.removeAttribute("dupliacteondrag"); + } } + else { + const type = root.getAttribute("type"); + let shouldPatch = false; + + switch (type) { + case "variables_get_reporter": + case "argument_reporter_boolean": + case "argument_reporter_number": + case "argument_reporter_string": + case "argument_reporter_array": + case "argument_reporter_custom": + shouldPatch = true; + break; + } - if (shouldPatch) { - root = promoteShadow(root) - if (!root) return; - let mutation = getDirectChildren(root, "mutation")[0]; + if (shouldPatch) { + root = promoteShadow(root) + if (!root) return; + let mutation = getDirectChildren(root, "mutation")[0]; - if (mutation) { - mutation.setAttribute("duplicateondrag", "true"); + if (mutation) { + mutation.setAttribute("duplicateondrag", "true"); + } + else { + mutation = Blockly.utils.xml.createElement("mutation"); + mutation.setAttribute("duplicateondrag", "true"); + root.appendChild(mutation); + } } - else { - mutation = Blockly.utils.xml.createElement("mutation"); - mutation.setAttribute("duplicateondrag", "true"); - root.appendChild(mutation); + else if (type === "variables_get" || hasNonShadowChild(root)) { + root = promoteShadow(root); } } - else if (type === "variables_get" || hasNonShadowChild(root)) { - root = promoteShadow(root); - } + } if (!root) return;