mirror of
https://github.com/google/blockly.git
synced 2026-01-18 14:27:12 +01:00
block library now exports valid xml and properly handles the imported xml in a robust way (#555)
This commit is contained in:
@@ -123,7 +123,7 @@ AppController.prototype.exportBlockLibraryToFile = function() {
|
||||
// Concatenate the xmls, each separated by a blank line.
|
||||
var blockLibText = this.formatBlockLibForExport_(blockLib);
|
||||
// Get file name.
|
||||
var filename = prompt('Enter the file name under which to save your block' +
|
||||
var filename = prompt('Enter the file name under which to save your block ' +
|
||||
'library.');
|
||||
// Download file if all necessary parameters are provided.
|
||||
if (filename) {
|
||||
@@ -138,38 +138,60 @@ AppController.prototype.exportBlockLibraryToFile = function() {
|
||||
* Converts an object mapping block type to xml to text file for output.
|
||||
* @private
|
||||
*
|
||||
* @param {!Object} blockXmlMap - object mapping block type to xml
|
||||
* @return {string} String of each block's xml separated by a new line.
|
||||
* @param {!Object} blockXmlMap - Object mapping block type to xml.
|
||||
* @return {string} Xml text containing the block xmls.
|
||||
*/
|
||||
AppController.prototype.formatBlockLibForExport_ = function(blockXmlMap) {
|
||||
var blockXmls = [];
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml', {
|
||||
'xmlns':"http://www.w3.org/1999/xhtml"
|
||||
});
|
||||
|
||||
// Append each block node to xml dom.
|
||||
for (var blockType in blockXmlMap) {
|
||||
blockXmls.push(blockXmlMap[blockType]);
|
||||
var blockXmlDom = Blockly.Xml.textToDom(blockXmlMap[blockType]);
|
||||
var blockNode = blockXmlDom.firstElementChild;
|
||||
xmlDom.appendChild(blockNode);
|
||||
}
|
||||
return blockXmls.join("\n\n");
|
||||
|
||||
// Return the xml text.
|
||||
return Blockly.Xml.domToText(xmlDom);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts imported block library to an object mapping block type to block xml.
|
||||
* @private
|
||||
*
|
||||
* @param {string} xmlText - String containing each block's xml optionally
|
||||
* separated by whitespace.
|
||||
* @param {string} xmlText - String representation of an xml with each block as
|
||||
* a child node.
|
||||
* @return {!Object} object mapping block type to xml text.
|
||||
*/
|
||||
AppController.prototype.formatBlockLibForImport_ = function(xmlText) {
|
||||
// Get array of xmls.
|
||||
var xmlText = goog.string.collapseWhitespace(xmlText);
|
||||
var blockXmls = goog.string.splitLimit(xmlText, '</xml>', 500);
|
||||
var xmlDom = Blockly.Xml.textToDom(xmlText);
|
||||
|
||||
// Create and populate map.
|
||||
// Get array of xmls. Use an asterisk (*) instead of a tag name for the XPath
|
||||
// selector, to match all elements at that level and get all factory_base
|
||||
// blocks.
|
||||
var blockNodes = goog.dom.xml.selectNodes(xmlDom, '*');
|
||||
|
||||
// Create empty map. The line below creates a truly empy object. It doesn't
|
||||
// have built-in attributes/functions such as length or toString.
|
||||
var blockXmlTextMap = Object.create(null);
|
||||
// The line above is equivalent of {} except that this object is TRULY
|
||||
// empty. It doesn't have built-in attributes/functions such as length or
|
||||
// toString.
|
||||
for (var i = 0, xmlText; xmlText = blockXmls[i]; i++) {
|
||||
|
||||
// Populate map.
|
||||
for (var i = 0, blockNode; blockNode = blockNodes[i]; i++) {
|
||||
|
||||
// Add outer xml tag to the block for proper injection in to the
|
||||
// main workspace.
|
||||
// Create DOM for XML.
|
||||
var xmlDom = goog.dom.createDom('xml', {
|
||||
'xmlns':"http://www.w3.org/1999/xhtml"
|
||||
});
|
||||
xmlDom.appendChild(blockNode);
|
||||
|
||||
var xmlText = Blockly.Xml.domToText(xmlDom);
|
||||
var blockType = this.getBlockTypeFromXml_(xmlText);
|
||||
// TODO(quachtina96): Make the xml pretty before storing in map.
|
||||
|
||||
blockXmlTextMap[blockType] = xmlText;
|
||||
}
|
||||
|
||||
@@ -185,9 +207,9 @@ AppController.prototype.formatBlockLibForImport_ = function(xmlText) {
|
||||
* @return {string} The block type that corresponds to the provided xml text.
|
||||
*/
|
||||
AppController.prototype.getBlockTypeFromXml_ = function(xmlText) {
|
||||
var xmlText = Blockly.Options.parseToolboxTree(xmlText);
|
||||
var xmlDom = Blockly.Xml.textToDom(xmlText);
|
||||
// Find factory base block.
|
||||
var factoryBaseBlockXml = xmlText.getElementsByTagName('block')[0];
|
||||
var factoryBaseBlockXml = xmlDom.getElementsByTagName('block')[0];
|
||||
// Get field elements from factory base.
|
||||
var fields = factoryBaseBlockXml.getElementsByTagName('field');
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
@@ -206,7 +228,8 @@ AppController.prototype.getBlockTypeFromXml_ = function(xmlText) {
|
||||
* @param {!Element} blockLibraryDropdown - HTML select element from which the
|
||||
* user selects a block to work on.
|
||||
*/
|
||||
AppController.prototype.onSelectedBlockChanged = function(blockLibraryDropdown) {
|
||||
AppController.prototype.onSelectedBlockChanged
|
||||
= function(blockLibraryDropdown) {
|
||||
// Get selected block type.
|
||||
var blockType = this.blockLibraryController.getSelectedBlockType(
|
||||
blockLibraryDropdown);
|
||||
|
||||
@@ -871,4 +871,4 @@ FactoryUtils.defineAndGetBlockTypes = function(blockDefsString, format) {
|
||||
}
|
||||
|
||||
return blockTypes;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user