From 14fa3b099973a9985bc7d7d921e6536270c56c83 Mon Sep 17 00:00:00 2001 From: Ed Sanders Date: Wed, 26 Jun 2013 14:56:59 +0100 Subject: [PATCH] Fix comparison of MW internal links We need to normalise titles so 'user:foo_bar' == 'User:Foo bar', and we also need to some HTML attribute removal as links from Parsoid will have href and rel set (again, this should be fixed in by Parsoid when the do the merging at their end). Bug: 49985 Change-Id: I5fb5bfc69c344ca4ce4803d7b6116074648a8d7e --- .../ve.dm.MWInternalLinkAnnotation.js | 29 +++++++++++++++++-- modules/ve/test/dm/ve.dm.mwExample.js | 9 ++++++ .../ve/ui/inspectors/ve.ui.MWLinkInspector.js | 3 +- .../widgets/ve.ui.MWLinkTargetInputWidget.js | 3 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js b/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js index 9715fd6dca..f0368dc21d 100644 --- a/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js +++ b/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js @@ -5,6 +5,8 @@ * @license The MIT License (MIT); see LICENSE.txt */ +/*global mw */ + /** * DataModel MediaWiki internal link annotation. * @@ -36,12 +38,15 @@ ve.dm.MWInternalLinkAnnotation.static.toDataElement = function ( domElements ) { // The href is simply the title, unless we're dealing with a page that has slashes in its name // in which case it's preceded by one or more instances of "./" or "../", so strip those /*jshint regexp:false */ - var matches = domElements[0].getAttribute( 'href' ).match( /^((?:\.\.?\/)*)(.*)$/ ); + var matches = domElements[0].getAttribute( 'href' ).match( /^((?:\.\.?\/)*)(.*)$/ ), + // Normalize capitalisation and underscores + normalizedTitle = ve.dm.MWInternalLinkAnnotation.static.normalizeTitle( matches[2] ); return { 'type': 'link/mwInternal', 'attributes': { 'hrefPrefix': matches[1], 'title': decodeURIComponent( matches[2] ).replace( /_/g, ' ' ), + 'normalizedTitle': normalizedTitle, 'origTitle': matches[2] } }; @@ -67,15 +72,35 @@ ve.dm.MWInternalLinkAnnotation.static.toDomElements = function ( dataElement, do return [ domElement ]; }; +/** + * Normalize title for comparison purposes + * @param {string} title Original title + * @returns {string} Normalized title + */ +ve.dm.MWInternalLinkAnnotation.static.normalizeTitle = function ( title ) { + var normalizedTitle = title; + try { + normalizedTitle = new mw.Title( title ).getPrefixedText(); + } catch ( e ) {} + return normalizedTitle; +}; + /* Methods */ ve.dm.MWInternalLinkAnnotation.prototype.getComparableObject = function () { return { 'type': this.getType(), - 'title': this.getAttribute( 'title' ) + 'normalizedTitle': this.getAttribute( 'normalizedTitle' ) }; }; +ve.dm.MWInternalLinkAnnotation.prototype.getComparableHtmlAttributes = function () { + var attributes = ve.dm.Annotation.prototype.getComparableHtmlAttributes.call( this ); + delete attributes.href; + delete attributes.rel; + return attributes; +}; + /* Registration */ ve.dm.modelRegistry.register( ve.dm.MWInternalLinkAnnotation ); diff --git a/modules/ve/test/dm/ve.dm.mwExample.js b/modules/ve/test/dm/ve.dm.mwExample.js index b06db96679..480d968ace 100644 --- a/modules/ve/test/dm/ve.dm.mwExample.js +++ b/modules/ve/test/dm/ve.dm.mwExample.js @@ -497,6 +497,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { @@ -512,6 +513,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { @@ -527,6 +529,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { @@ -626,6 +629,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Foo/Bar', 'origTitle': 'Foo/Bar', + 'normalizedTitle': 'Foo/Bar', 'hrefPrefix': './../../../' }, 'htmlAttributes': [ { 'values': { @@ -641,6 +645,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Foo/Bar', 'origTitle': 'Foo/Bar', + 'normalizedTitle': 'Foo/Bar', 'hrefPrefix': './../../../' }, 'htmlAttributes': [ { 'values': { @@ -656,6 +661,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Foo/Bar', 'origTitle': 'Foo/Bar', + 'normalizedTitle': 'Foo/Bar', 'hrefPrefix': './../../../' }, 'htmlAttributes': [ { 'values': { @@ -1008,6 +1014,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { 'href': './Bar', 'rel': 'mw:WikiLink', 'data-parsoid': '{}' } } ] @@ -1020,6 +1027,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { 'href': './Bar', 'rel': 'mw:WikiLink', 'data-parsoid': '{}' } } ] @@ -1032,6 +1040,7 @@ ve.dm.mwExample.domToDataCases = { 'attributes': { 'title': 'Bar', 'origTitle': 'Bar', + 'normalizedTitle': 'Bar', 'hrefPrefix': './' }, 'htmlAttributes': [ { 'values': { 'href': './Bar', 'rel': 'mw:WikiLink', 'data-parsoid': '{}' } } ] diff --git a/modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js b/modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js index 6c683e7e23..6e9b683fcd 100644 --- a/modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js +++ b/modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js @@ -73,7 +73,8 @@ ve.ui.MWLinkInspector.prototype.getAnnotationFromTarget = function ( target ) { return new ve.dm.MWInternalLinkAnnotation( { 'type': 'link/mwInternal', 'attributes': { - 'title': target + 'title': target, + 'normalizedTitle': ve.dm.MWInternalLinkAnnotation.static.normalizeTitle( target ) } } ); } diff --git a/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js b/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js index 8cacd626e3..cb72a3bc39 100644 --- a/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js +++ b/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js @@ -190,7 +190,8 @@ ve.ui.MWLinkTargetInputWidget.prototype.getInternalLinkAnnotationFromTitle = fun return new ve.dm.MWInternalLinkAnnotation( { 'type': 'link/mwInternal', 'attributes': { - 'title': target + 'title': target, + 'normalizedTitle': ve.dm.MWInternalLinkAnnotation.static.normalizeTitle( target ) } } ); };