jenkins-bot has submitted this change and it was merged. Change subject: Properly escape question marks in page titles in <head>. ......................................................................
Properly escape question marks in page titles in <head>. The unescaped question mark in the <base href> caused OCG problems on the page [[:enwikibooks:A-level Physics (Advancing Physics)/What is a wave?/Worked Solutions]] and it turns out that the RDF isVersionOf property link had the same buglet. Add a mocha test to sanity-check our wikilinks and resource links. Change-Id: I0f1b92ba569d82832038ccbc5cd722d6d9cb1aaf --- M lib/mediawiki.DOMPostProcessor.js A tests/mocha/parse.js D tests/mocha/util.js 3 files changed, 94 insertions(+), 56 deletions(-) Approvals: Arlolra: Looks good to me, approved jenkins-bot: Verified diff --git a/lib/mediawiki.DOMPostProcessor.js b/lib/mediawiki.DOMPostProcessor.js index c161b02..b41b663 100644 --- a/lib/mediawiki.DOMPostProcessor.js +++ b/lib/mediawiki.DOMPostProcessor.js @@ -324,7 +324,8 @@ 'property': 'mw:parsoidVersion', 'content': env.conf.parsoid.version.toString() }); - var wikiPageUrl = env.conf.wiki.baseURI + env.page.name; + var wikiPageUrl = env.conf.wiki.baseURI + + env.page.name.split('/').map(encodeURIComponent).join('/'); appendToHead(document, 'link', { rel: 'dc:isVersionOf', href: wikiPageUrl }); diff --git a/tests/mocha/parse.js b/tests/mocha/parse.js new file mode 100644 index 0000000..6bba234 --- /dev/null +++ b/tests/mocha/parse.js @@ -0,0 +1,92 @@ +/** Test cases for lib/mediawiki.Util.js */ +'use strict'; +/*global describe, it, Promise*/ + +require("es6-shim"); +require("prfun"); + +var should = require("chai").should(); + +var url = require('url'); + +var MWParserEnvironment = require('../../lib/mediawiki.parser.environment.js' ).MWParserEnvironment, + Util = require('../../lib/mediawiki.Util.js').Util, + ParsoidConfig = require('../../lib/mediawiki.ParsoidConfig' ).ParsoidConfig; + +describe( 'ParserPipelineFactory', function() { + var parsoidConfig = new ParsoidConfig( null, { defaultWiki: 'enwiki' } ); + + describe( 'parse()', function() { + + var parse = function(src, page_name, expansions) { + return new Promise(function(resolve, reject) { + MWParserEnvironment.getParserEnv( parsoidConfig, null, 'enwiki', page_name || 'Main_Page', null, function ( err, env ) { + if (err) { return reject(err); } + env.setPageSrcInfo(src); + var pipeline = env.pipelineFactory; + Promise.promisify( pipeline.parse, false, pipeline )( + env, env.page.src, expansions + ).then( resolve, reject ); + }); + }); + }; + + it('should create a sane document from a short string', function() { + return parse('foo').then(function(doc) { + doc.should.have.property('nodeName', '#document'); + doc.outerHTML.startsWith('<!DOCTYPE html><html').should.equal(true); + doc.outerHTML.endsWith('</body></html>').should.equal(true); + // verify that body has only one <html> tag, one <body> tag, etc. + doc.childNodes.length.should.equal(2);// <!DOCTYPE> and <html> + doc.firstChild.nodeName.should.equal('html'); + doc.lastChild.nodeName.should.equal('HTML'); + // <html> children should be <head> and <body> + var html = doc.documentElement; + html.childNodes.length.should.equal(2); + html.firstChild.nodeName.should.equal('HEAD'); + html.lastChild.nodeName.should.equal('BODY'); + // <body> should have one child, <p> + var body = doc.body; + body.childElementCount.should.equal(1); + body.firstElementChild.nodeName.should.equal('P'); + var p = doc.body.firstElementChild; + p.innerHTML.should.equal('foo'); + }); + }); + + it('should handle page titles with embedded ?', function() { + return parse('[[Foo?/Bar]] [[File:Foo.jpg]]', 'A/B?/C').then(function(doc) { + var els; + els = doc.querySelectorAll('HEAD > BASE[href]'); + els.length.should.equal(1); + var basehref = els[0].getAttribute('href'); + // ensure base is a prototocol-relative url + basehref = basehref.replace(/^https?:/, ''); + + // check wikilink + els = doc.querySelectorAll('A[rel="mw:WikiLink"][href]'); + els.length.should.equal(1); + var ahref1 = els[0].getAttribute('href'); + url.resolve(basehref, ahref1).should.equal( + '//en.wikipedia.org/wiki/Foo%3F/Bar' + ); + + // check image link + els = doc.querySelectorAll('*[typeof="mw:Image"] > A[href]'); + els.length.should.equal(1); + var ahref2 = els[0].getAttribute('href'); + url.resolve(basehref, ahref2).should.equal( + '//en.wikipedia.org/wiki/File:Foo.jpg' + ); + + // check image resource + els = doc.querySelectorAll('*[typeof="mw:Image"] IMG[resource]'); + els.length.should.equal(1); + var ahref3 = els[0].getAttribute('resource'); + url.resolve(basehref, ahref3).should.equal( + '//en.wikipedia.org/wiki/File:Foo.jpg' + ); + }); + }); + }); +}); diff --git a/tests/mocha/util.js b/tests/mocha/util.js deleted file mode 100644 index 08e0380..0000000 --- a/tests/mocha/util.js +++ /dev/null @@ -1,55 +0,0 @@ -/** Test cases for lib/mediawiki.Util.js */ -'use strict'; -/*global describe, it, Promise*/ - -require("es6-shim"); -require("prfun"); - -var should = require("chai").should(); - -var MWParserEnvironment = require('../../lib/mediawiki.parser.environment.js' ).MWParserEnvironment, - Util = require('../../lib/mediawiki.Util.js').Util, - ParsoidConfig = require('../../lib/mediawiki.ParsoidConfig' ).ParsoidConfig; - -describe( 'mediawiki.Util', function() { - var parsoidConfig = new ParsoidConfig( null, { defaultWiki: 'enwiki' } ); - - describe( 'parse()', function() { - - var parse = function(src, expansions) { - return new Promise(function(resolve, reject) { - MWParserEnvironment.getParserEnv( parsoidConfig, null, 'enwiki', 'Main_Page', null, function ( err, env ) { - if (err) { return reject(err); } - env.setPageSrcInfo(src); - var pipeline = env.pipelineFactory; - Promise.promisify( pipeline.parse, false, pipeline )( - env, env.page.src, expansions - ).then( resolve, reject ); - }); - }); - }; - - it('should create a sane document from an empty string', function() { - return parse('foo').then(function(doc) { - doc.should.have.property('nodeName', '#document'); - doc.outerHTML.startsWith('<!DOCTYPE html><html').should.equal(true); - doc.outerHTML.endsWith('</body></html>').should.equal(true); - // verify that body has only one <html> tag, one <body> tag, etc. - doc.childNodes.length.should.equal(2);// <!DOCTYPE> and <html> - doc.firstChild.nodeName.should.equal('html'); - doc.lastChild.nodeName.should.equal('HTML'); - // <html> children should be <head> and <body> - var html = doc.documentElement; - html.childNodes.length.should.equal(2); - html.firstChild.nodeName.should.equal('HEAD'); - html.lastChild.nodeName.should.equal('BODY'); - // <body> should have one child, <p> - var body = doc.body; - body.childElementCount.should.equal(1); - body.firstElementChild.nodeName.should.equal('P'); - var p = doc.body.firstElementChild; - p.innerHTML.should.equal('foo'); - }); - }); - }); -}); -- To view, visit https://gerrit.wikimedia.org/r/171858 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I0f1b92ba569d82832038ccbc5cd722d6d9cb1aaf Gerrit-PatchSet: 3 Gerrit-Project: mediawiki/services/parsoid Gerrit-Branch: master Gerrit-Owner: Cscott <canan...@wikimedia.org> Gerrit-Reviewer: Arlolra <abrea...@wikimedia.org> Gerrit-Reviewer: Cscott <canan...@wikimedia.org> Gerrit-Reviewer: Marcoil <marc...@wikimedia.org> Gerrit-Reviewer: Subramanya Sastry <ssas...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits