diff --git a/modules/ve/init/mw/ve.init.mw.Target.js b/modules/ve/init/mw/ve.init.mw.Target.js index 743217f758..037b40f8e3 100644 --- a/modules/ve/init/mw/ve.init.mw.Target.js +++ b/modules/ve/init/mw/ve.init.mw.Target.js @@ -182,8 +182,7 @@ ve.init.mw.Target.onLoad = function ( response ) { /** * Handle both DOM and modules being loaded and ready. * - * This method is called within the context of a target instance. After the load event is emitted - * this.doc is cleared, allowing it to be garbage collected. + * This method is called within the context of a target instance. * * @static * @method @@ -192,8 +191,6 @@ ve.init.mw.Target.onLoad = function ( response ) { ve.init.mw.Target.onReady = function () { this.loading = false; this.emit( 'load', this.doc ); - // Release DOM data - this.doc = null; }; /** @@ -358,6 +355,36 @@ ve.init.mw.Target.onSerializeError = function ( jqXHR, status, error ) { /* Methods */ +/** + * Get HTML to send to Parsoid. This takes a document generated by the converter and + * transplants the head tag from the old document into it, as well as the attributes on the + * html and body tags. + * + * @param {HTMLDocument} newDoc Document generated by ve.dm.Converter. Will be modified. + * @returns {string} Full HTML document + */ +ve.init.mw.Target.prototype.getHtml = function ( newDoc ) { + var i, len, oldDoc = this.doc; + + function copyAttributes( from, to ) { + var i, len; + for ( i = 0, len = from.attributes.length; i < len; i++ ) { + to.setAttribute( from.attributes[i].name, from.attributes[i].value ); + } + } + + // Copy the head from the old document + for ( i = 0, len = oldDoc.head.childNodes.length; i < len; i++ ) { + newDoc.head.appendChild( oldDoc.head.childNodes[i].cloneNode( true ) ); + } + // Copy attributes from the old document for the html, head and body + copyAttributes( oldDoc.documentElement, newDoc.documentElement ); + copyAttributes( oldDoc.head, newDoc.head ); + copyAttributes( oldDoc.body, newDoc.body ); + return '' + ve.properOuterHtml( newDoc.documentElement ); +}; + + /** * Get DOM data from the Parsoid API. * @@ -430,7 +457,7 @@ ve.init.mw.Target.prototype.save = function ( doc, options ) { 'oldid': this.oldid, 'basetimestamp': this.baseTimeStamp, 'starttimestamp': this.startTimeStamp, - 'html': ve.properInnerHtml( doc.body ), // TODO make this send the whole document in the future + 'html': this.getHtml( doc ), 'token': this.editToken, 'summary': options.summary, 'minor': Number( options.minor ), @@ -461,7 +488,7 @@ ve.init.mw.Target.prototype.showChanges = function ( doc ) { 'paction': 'diff', 'page': this.pageName, 'oldid': this.oldid, - 'html': ve.properInnerHtml( doc.body ), // TODO make this send the whole document in the future + 'html': this.getHtml( doc ), // TODO: API required editToken, though not relevant for diff 'token': this.editToken }, @@ -549,7 +576,7 @@ ve.init.mw.Target.prototype.serialize = function ( doc, callback ) { 'data': { 'action': 'visualeditor', 'paction': 'serialize', - 'html': ve.properInnerHtml( doc.body ), // TODO make this send the whole document in the future + 'html': this.getHtml( doc ), 'page': this.pageName, 'oldid': this.oldid, 'token': this.editToken, @@ -594,7 +621,7 @@ ve.init.mw.Target.prototype.reportProblem = function ( message ) { store, internalList ).getData(), 'editedData': editedData, - 'editedHtml': ve.properInnerHtml( ve.dm.converter.getDomFromData( editedData, store, internalList ).body ), + 'editedHtml': this.getHtml( ve.dm.converter.getDomFromData( editedData, store, internalList ) ), 'store': doc.data.getUsedStoreValues(), 'wiki': mw.config.get( 'wgDBname' ) };