From c06a86587c522af632fa9ceb6260da6a8a429418 Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Wed, 26 Mar 2014 21:49:59 -0700 Subject: [PATCH] Deal with Parsoid's protocol-relative tags in a DOMParser world Protocol-relative tags are fine when the iframe trick is used because the iframe inherits a default base URL from the parent document, so if the is relative it can be resolved against that. However, a document created with DOMParser (or document.implementation, oops!) won't inherit anything, so anything other than a fully absolute will just break. To make Parsoid's relative work anyway, resolve it in the context of the main document, then write the resolved version back into the tag. Change-Id: I7261bd5dbe9ec1f4077a4e5a00bd2a03ac237ca0 --- modules/ve-mw/init/ve.init.mw.Target.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/ve-mw/init/ve.init.mw.Target.js b/modules/ve-mw/init/ve.init.mw.Target.js index 3455a98180..06ec8f78b9 100644 --- a/modules/ve-mw/init/ve.init.mw.Target.js +++ b/modules/ve-mw/init/ve.init.mw.Target.js @@ -309,6 +309,27 @@ ve.init.mw.Target.static.apiRequest = function ( data, settings ) { return $.ajax( settings ); }; +/** + * Take a target document with a possibly relative base URL, and modify it to be absolute. + * The base URL of the target document is resolved using the base URL of the source document. + * @param {HTMLDocument} targetDoc Document whose base URL should be resolved + * @param {HTMLDocument} sourceDoc Document whose base URL should be used for resolution + */ +ve.init.mw.Target.static.fixBase = function ( targetDoc, sourceDoc ) { + var $base; + if ( !targetDoc.baseURI ) { + $base = $( 'base', targetDoc ); + if ( $base.length ) { + // Modify the existing tag + $base.attr( 'href', ve.resolveUrl( $base.attr( 'href' ), sourceDoc ) ); + } else { + // No tag, add one + $base = $( '', targetDoc ).attr( 'href', sourceDoc.baseURI ); + $( 'head', sourceDoc ).append( $base ); + } + } +}; + /** * Handle the RL modules for VE and registered plugin modules being loaded. * @@ -367,6 +388,9 @@ ve.init.mw.Target.onLoad = function ( response ) { this.originalHtml = data.content; this.doc = ve.createDocumentFromHtml( this.originalHtml ); + // Parsoid outputs a protocol-relative tag, so absolutize it + this.constructor.static.fixBase( this.doc, document ); + this.remoteNotices = ve.getObjectValues( data.notices ); this.$checkboxes = $( ve.getObjectValues( data.checkboxes ).join( '' ) ); // Populate checkboxes with default values for minor and watch