diff --git a/blockly_compressed.js b/blockly_compressed.js index 8fdab6f2c..dc6efca41 100644 --- a/blockly_compressed.js +++ b/blockly_compressed.js @@ -43,7 +43,8 @@ Blockly.Events.fromJson=function(a,b){switch(a.type){case Blockly.Events.CREATE: new Blockly.Events.VarRename(null,"");break;case Blockly.Events.UI:c=new Blockly.Events.Ui(null);break;case Blockly.Events.COMMENT_CREATE:c=new Blockly.Events.CommentCreate(null);break;case Blockly.Events.COMMENT_CHANGE:c=new Blockly.Events.CommentChange(null);break;case Blockly.Events.COMMENT_MOVE:c=new Blockly.Events.CommentMove(null);break;case Blockly.Events.COMMENT_DELETE:c=new Blockly.Events.CommentDelete(null);break;default:throw Error("Unknown event type.");}c.fromJson(a);c.workspaceId=b.id; return c};Blockly.Events.disableOrphans=function(a){if(a.type==Blockly.Events.MOVE||a.type==Blockly.Events.CREATE){var b=Blockly.Workspace.getById(a.workspaceId);if(a=b.getBlockById(a.blockId)){var c=a.getParent();if(c&&c.isEnabled())for(b=a.getDescendants(!1),a=0;c=b[a];a++)c.setEnabled(!0);else if((a.outputConnection||a.previousConnection)&&!b.isDragging()){do a.setEnabled(!1),a=a.getNextBlock();while(a)}}}}; Blockly.Events.Abstract=function(){this.workspaceId=void 0;this.group=Blockly.Events.group_;this.recordUndo=Blockly.Events.recordUndo};Blockly.Events.Abstract.prototype.toJson=function(){var a={type:this.type};this.group&&(a.group=this.group);return a};Blockly.Events.Abstract.prototype.fromJson=function(a){this.group=a.group};Blockly.Events.Abstract.prototype.isNull=function(){return!1};Blockly.Events.Abstract.prototype.run=function(a){}; -Blockly.Events.Abstract.prototype.getEventWorkspace_=function(){var a=Blockly.Workspace.getById(this.workspaceId);if(!a)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return a};Blockly.utils.object={};Blockly.utils.object.inherits=function(a,b){a.superClass_=b.prototype;a.prototype=Object.create(b.prototype);a.prototype.constructor=a};Blockly.utils.object.mixin=function(a,b){for(var c in b)a[c]=b[c]};Blockly.utils.object.values=function(a){return Object.values?Object.values(a):Object.keys(a).map(function(b){return a[b]})};Blockly.utils.xml={};Blockly.utils.xml.NAME_SPACE="https://developers.google.com/blockly/xml";Blockly.utils.xml.createElement=function(a){return document.createElementNS(Blockly.utils.xml.NAME_SPACE,a)};Blockly.utils.xml.createTextNode=function(a){return document.createTextNode(a)};Blockly.utils.xml.textToDomDocument=function(a){return(new DOMParser).parseFromString(a,"text/xml")};Blockly.utils.xml.domToText=function(a){return(new XMLSerializer).serializeToString(a)};Blockly.Events.BlockBase=function(a){Blockly.Events.BlockBase.superClass_.constructor.call(this);this.blockId=a.id;this.workspaceId=a.workspace.id};Blockly.utils.object.inherits(Blockly.Events.BlockBase,Blockly.Events.Abstract);Blockly.Events.BlockBase.prototype.toJson=function(){var a=Blockly.Events.BlockBase.superClass_.toJson.call(this);a.blockId=this.blockId;return a}; +Blockly.Events.Abstract.prototype.getEventWorkspace_=function(){var a=Blockly.Workspace.getById(this.workspaceId);if(!a)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return a};Blockly.utils.object={};Blockly.utils.object.inherits=function(a,b){a.superClass_=b.prototype;a.prototype=Object.create(b.prototype);a.prototype.constructor=a};Blockly.utils.object.mixin=function(a,b){for(var c in b)a[c]=b[c]};Blockly.utils.object.values=function(a){return Object.values?Object.values(a):Object.keys(a).map(function(b){return a[b]})};Blockly.utils.xml={};Blockly.utils.xml.NAME_SPACE="https://developers.google.com/blockly/xml";Blockly.utils.xml.document=function(){return document};Blockly.utils.xml.createElement=function(a){return Blockly.utils.xml.document().createElementNS(Blockly.utils.xml.NAME_SPACE,a)};Blockly.utils.xml.createTextNode=function(a){return Blockly.utils.xml.document().createTextNode(a)};Blockly.utils.xml.textToDomDocument=function(a){return(new DOMParser).parseFromString(a,"text/xml")}; +Blockly.utils.xml.domToText=function(a){return(new XMLSerializer).serializeToString(a)};Blockly.Events.BlockBase=function(a){Blockly.Events.BlockBase.superClass_.constructor.call(this);this.blockId=a.id;this.workspaceId=a.workspace.id};Blockly.utils.object.inherits(Blockly.Events.BlockBase,Blockly.Events.Abstract);Blockly.Events.BlockBase.prototype.toJson=function(){var a=Blockly.Events.BlockBase.superClass_.toJson.call(this);a.blockId=this.blockId;return a}; Blockly.Events.BlockBase.prototype.fromJson=function(a){Blockly.Events.BlockBase.superClass_.fromJson.call(this,a);this.blockId=a.blockId};Blockly.Events.Change=function(a,b,c,d,e){a&&(Blockly.Events.Change.superClass_.constructor.call(this,a),this.element=b,this.name=c,this.oldValue=d,this.newValue=e)};Blockly.utils.object.inherits(Blockly.Events.Change,Blockly.Events.BlockBase);Blockly.Events.BlockChange=Blockly.Events.Change;Blockly.Events.Change.prototype.type=Blockly.Events.CHANGE; Blockly.Events.Change.prototype.toJson=function(){var a=Blockly.Events.Change.superClass_.toJson.call(this);a.element=this.element;this.name&&(a.name=this.name);a.newValue=this.newValue;return a};Blockly.Events.Change.prototype.fromJson=function(a){Blockly.Events.Change.superClass_.fromJson.call(this,a);this.element=a.element;this.name=a.name;this.newValue=a.newValue};Blockly.Events.Change.prototype.isNull=function(){return this.oldValue==this.newValue}; Blockly.Events.Change.prototype.run=function(a){var b=this.getEventWorkspace_().getBlockById(this.blockId);if(b)switch(b.mutator&&b.mutator.setVisible(!1),a=a?this.newValue:this.oldValue,this.element){case "field":(b=b.getField(this.name))?b.setValue(a):console.warn("Can't set non-existent field: "+this.name);break;case "comment":b.setCommentText(a||null);break;case "collapsed":b.setCollapsed(a);break;case "disabled":b.setEnabled(!a);break;case "inline":b.setInputsInline(a);break;case "mutation":var c= diff --git a/core/utils/xml.js b/core/utils/xml.js index 87854714c..082844ec1 100644 --- a/core/utils/xml.js +++ b/core/utils/xml.js @@ -37,6 +37,16 @@ goog.provide('Blockly.utils.xml'); */ Blockly.utils.xml.NAME_SPACE = 'https://developers.google.com/blockly/xml'; +/** + * Get the document object. This method is overridden in the Node.js build of + * Blockly. See gulpfile.js, package-blockly-node task. + * @return {!Document} The document object. + * @public + */ +Blockly.utils.xml.document = function() { + return document; +}; + /** * Create DOM element for XML. * @param {string} tagName Name of DOM element. @@ -44,8 +54,8 @@ Blockly.utils.xml.NAME_SPACE = 'https://developers.google.com/blockly/xml'; * @public */ Blockly.utils.xml.createElement = function(tagName) { - // TODO (#2082): Support node.js. - return document.createElementNS(Blockly.utils.xml.NAME_SPACE, tagName); + return Blockly.utils.xml.document().createElementNS( + Blockly.utils.xml.NAME_SPACE, tagName); }; /** @@ -55,13 +65,11 @@ Blockly.utils.xml.createElement = function(tagName) { * @public */ Blockly.utils.xml.createTextNode = function(text) { - // TODO (#2082): Support node.js. - return document.createTextNode(text); + return Blockly.utils.xml.document().createTextNode(text); }; /** - * Converts an XML string into a DOM tree. This method will be overridden in - * the Node.js build of Blockly. See gulpfile.js, blockly_javascript_en task. + * Converts an XML string into a DOM tree. * @param {string} text XML string. * @return {Document} The DOM document. * @throws if XML doesn't parse. @@ -80,7 +88,6 @@ Blockly.utils.xml.textToDomDocument = function(text) { * @public */ Blockly.utils.xml.domToText = function(dom) { - // TODO (#2082): Support node.js. var oSerializer = new XMLSerializer(); return oSerializer.serializeToString(dom); }; diff --git a/gulpfile.js b/gulpfile.js index f7614dc1f..4624f6da0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -453,13 +453,12 @@ gulp.task('package-blockly-node', function() { return gulp.src('blockly_compressed.js') .pipe(gulp.insert.append(` if (typeof DOMParser !== 'function') { - var JSDOM = require('jsdom').JSDOM; - var window = (new JSDOM()).window; - var document = window.document; - var Element = window.Element; - Blockly.utils.xml.textToDomDocument = function(text) { - var jsdom = new JSDOM(text, { contentType: 'text/xml' }); - return jsdom.window.document; + var DOMParser = require("jsdom/lib/jsdom/living").DOMParser; + var XMLSerializer = require("jsdom/lib/jsdom/living").XMLSerializer; + var doc = Blockly.utils.xml.textToDomDocument( + ''); + Blockly.utils.xml.document = function() { + return doc; }; }`)) .pipe(packageCommonJS('Blockly', [])) diff --git a/tests/node/run_node_test.js b/tests/node/run_node_test.js index cc76ebfab..c2c9847ee 100644 --- a/tests/node/run_node_test.js +++ b/tests/node/run_node_test.js @@ -26,25 +26,33 @@ var assert = require('chai').assert; var Blockly = require('../../dist/'); var xmlText = ` - - - - Hello from Blockly! - - - + + + + Hello from Blockly! + + + `; suite('Test Node.js', function() { test('Import XML', function() { - assert.doesNotThrow(function() { - const xml = Blockly.Xml.textToDom(xmlText); + const xml = Blockly.Xml.textToDom(xmlText); - // Create workspace and import the XML - const workspace = new Blockly.Workspace(); - Blockly.Xml.domToWorkspace(xml, workspace); + // Create workspace and import the XML + const workspace = new Blockly.Workspace(); + Blockly.Xml.domToWorkspace(xml, workspace); + }); + test('Roundtrip XML', function() { + const xml = Blockly.Xml.textToDom(xmlText); - }, "Failed to import XML"); + const workspace = new Blockly.Workspace(); + Blockly.Xml.domToWorkspace(xml, workspace); + + var headlessXml = Blockly.Xml.workspaceToDom(workspace, true); + var headlessText = Blockly.Xml.domToPrettyText(headlessXml); + + assert.equal(headlessText, xmlText, 'equal'); }); test('Generate Code', function() { const xml = Blockly.Xml.textToDom(xmlText);