mirror of
https://github.com/google/blockly.git
synced 2026-03-14 17:20:11 +01:00
feat: add top level save and load functions for JSO serialization (#5132)
* Add top-level serialization API * Add using JSO system in serializer tests * Make compiler happy
This commit is contained in:
committed by
alschmiedt
parent
28ff2c84c6
commit
d3a9e517b2
@@ -82,5 +82,4 @@ goog.require('Blockly.zelos.Renderer');
|
||||
// Classic is the default theme.
|
||||
goog.require('Blockly.Themes.Classic');
|
||||
|
||||
goog.require('Blockly.serialization.blocks');
|
||||
goog.require('Blockly.serialization.variables');
|
||||
goog.require('Blockly.serialization.workspaces');
|
||||
|
||||
@@ -17,6 +17,8 @@ goog.module.declareLegacyNamespace();
|
||||
const Block = goog.requireType('Blockly.Block');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const Connection = goog.requireType('Blockly.Connection');
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const Workspace = goog.requireType('Blockly.Workspace');
|
||||
const Xml = goog.require('Blockly.Xml');
|
||||
const inputTypes = goog.require('Blockly.inputTypes');
|
||||
|
||||
@@ -255,3 +257,14 @@ const saveConnection = function(connection) {
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the block represented by the given state into the given workspace.
|
||||
* @param {!State} state The state of a block to deserialize into the workspace.
|
||||
* @param {!Workspace} workspace The workspace to add the block to.
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const load = function(state, workspace) {
|
||||
// Temporarily NOP while connecting things together.
|
||||
};
|
||||
exports.load = load;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2021 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Contains top-level functions for serialization of the workspace
|
||||
* to JavaScript objects.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The top level namespace for JavaScript Object serialization.
|
||||
* @namespace Blockly.serialization
|
||||
*/
|
||||
goog.module('Blockly.serialization');
|
||||
goog.module.declareLegacyNamespace();
|
||||
80
core/serialization/workspaces.js
Normal file
80
core/serialization/workspaces.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2021 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Contains top-level functions for serializing workspaces to
|
||||
* plain JavaScript objects.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.serialization.workspaces');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const Workspace = goog.require('Blockly.Workspace');
|
||||
const blocks = goog.require('Blockly.serialization.blocks');
|
||||
const variables = goog.require('Blockly.serialization.variables');
|
||||
|
||||
|
||||
/**
|
||||
* Returns the state of the workspace as a plain JavaScript object.
|
||||
* @param {!Workspace} workspace The workspace to serialize.
|
||||
* @return {!Object<string, *>} The serialized state of the workspace.
|
||||
*/
|
||||
const save = function(workspace) {
|
||||
const state = Object.create(null);
|
||||
|
||||
// TODO: Switch this to use plugin serialization system (once it is built).
|
||||
const variableState = [];
|
||||
const vars = workspace.getAllVariables();
|
||||
for (let i = 0; i < vars.length; i++) {
|
||||
variableState.push(variables.save(vars[i]));
|
||||
}
|
||||
if (variableState.length) {
|
||||
state['variables'] = variableState;
|
||||
}
|
||||
|
||||
const blockState = [];
|
||||
for (let block of workspace.getTopBlocks(false)) {
|
||||
blockState.push(
|
||||
blocks.save(block, {addCoordinates: true}));
|
||||
}
|
||||
if (blockState.length) {
|
||||
// This is an object to support adding language version later.
|
||||
state['blocks'] = {
|
||||
'blocks': blockState
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
exports.save = save;
|
||||
|
||||
/**
|
||||
* Loads the variable represented by the given state into the given workspace.
|
||||
* @param {!Object<string, *>} state The state of the workspace to deserialize
|
||||
* into the workspace.
|
||||
* @param {!Workspace} workspace The workspace to add the new state to.
|
||||
*/
|
||||
const load = function(state, workspace) {
|
||||
// TODO: Switch this to use plugin serialization system (once it is built).
|
||||
// TODO: Add something for clearing the state before deserializing.
|
||||
|
||||
if (state['variables']) {
|
||||
const variableStates = state['variables'];
|
||||
for (let i = 0; i < variableStates.length; i++) {
|
||||
variables.load(variableStates[i], workspace);
|
||||
}
|
||||
}
|
||||
|
||||
if (state['blocks']) {
|
||||
const blockStates = state['blocks']['blocks'];
|
||||
for (let i = 0; i < blockStates.length; i++) {
|
||||
blocks.load(blockStates[i], workspace);
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.load = load;
|
||||
@@ -193,12 +193,12 @@ goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['B
|
||||
goog.addDependency('../../core/renderers/zelos/measurables/top_row.js', ['Blockly.zelos.TopRow'], ['Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.serialization.variables', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.workspaces', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Xml', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/serialization.js', ['Blockly.serialization'], [], {'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/variables.js', ['Blockly.serialization.variables'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/workspaces.js', ['Blockly.serialization.workspaces'], ['Blockly.Workspace', 'Blockly.serialization.blocks', 'Blockly.serialization.variables'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
|
||||
@@ -193,12 +193,12 @@ goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['B
|
||||
goog.addDependency('../../core/renderers/zelos/measurables/top_row.js', ['Blockly.zelos.TopRow'], ['Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.serialization.variables', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.workspaces', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Xml', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/serialization.js', ['Blockly.serialization'], [], {'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/variables.js', ['Blockly.serialization.variables'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/serialization/workspaces.js', ['Blockly.serialization.workspaces'], ['Blockly.Workspace', 'Blockly.serialization.blocks', 'Blockly.serialization.variables'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
|
||||
@@ -1730,14 +1730,16 @@ Serializer.testSuites = [
|
||||
];
|
||||
|
||||
var runSerializerTestSuite = (serializer, deserializer, testSuite) => {
|
||||
const workspaces = Blockly.serialization.workspaces;
|
||||
|
||||
const createTestFunction = function(test) {
|
||||
return function() {
|
||||
Blockly.Xml.domToWorkspace(
|
||||
Blockly.Xml.textToDom(test.xml), this.workspace);
|
||||
if (serializer && deserializer) {
|
||||
// TODO: Add support for custom serializeers and deserializers.
|
||||
// Will be added once we have the JSO format working.
|
||||
const save = serializer(workspaces.save(this.workspace));
|
||||
this.workspace.clear();
|
||||
workspaces.load(deserializer(save), this.workspace);
|
||||
}
|
||||
var newXml = Blockly.Xml.workspaceToDom(this.workspace);
|
||||
chai.assert.equal(Blockly.Xml.domToText(newXml), test.xml);
|
||||
@@ -1770,3 +1772,5 @@ var runSerializerTestSuite = (serializer, deserializer, testSuite) => {
|
||||
};
|
||||
|
||||
runSerializerTestSuite(null, null, Serializer);
|
||||
Serializer.skip = true;
|
||||
runSerializerTestSuite(state => state, state => state, Serializer);
|
||||
|
||||
Reference in New Issue
Block a user