Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export {
StatusIndicatorLabel,
StatusButtonState,
} from "./status_indicator_label";
export * from "./xml";

export function inject(container: Element, options: Blockly.BlocklyOptions) {
registerScratchFieldAngle();
Expand Down
57 changes: 57 additions & 0 deletions src/xml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import * as Blockly from "blockly/core";
import { ScratchVariableModel } from "./scratch_variable_model";

/**
* Clears the workspace and loads the given serialized state.
*
* @param xml XML representation of a Blockly workspace.
* @param workspace The workspace to load the serialized data onto.
*/
export function clearWorkspaceAndLoadFromXml(
xml: Element,
workspace: Blockly.WorkspaceSvg
): string[] {
workspace.setResizesEnabled(false);
Blockly.Events.setGroup(true);
workspace.clear();

// Manually load variables to include the cloud and local properties that core
// Blockly is unaware of.
for (const variable of xml.querySelectorAll("variables variable")) {
const id = variable.getAttribute("id");
if (!id) continue;
const type = variable.getAttribute("type");
const name = variable.textContent;
const isLocal = variable.getAttribute("islocal") === "true";
const isCloud = variable.getAttribute("iscloud") === "true";

const variableModel = new ScratchVariableModel(
workspace,
name,
type,
id,
isLocal,
isCloud
);
Blockly.Events.fire(
new (Blockly.Events.get(Blockly.Events.VAR_CREATE))(variableModel)
);
workspace.getVariableMap().addVariable(variableModel);
}

// Remove the `variables` element from the XML to prevent Blockly from
// throwing or stomping on the variables we created.
xml.querySelector("variables").remove();

// Defer to core for the rest of the deserialization.
const blockIds = Blockly.Xml.domToWorkspace(xml, workspace);

workspace.setResizesEnabled(true);
return blockIds;
}