From: Ed Sanders Date: Fri, 7 Oct 2016 17:14:03 +0000 (-0400) Subject: Add exceptions in mw.Title where mb_strtoupper doesn't match String.toUpperCase X-Git-Tag: 1.31.0-rc.0~4779^2 X-Git-Url: http://git.cyclocoop.org/?a=commitdiff_plain;h=edf4dfe7566243f5dccc2270d2391878a2af72ad;p=lhc%2Fweb%2Fwiklou.git Add exceptions in mw.Title where mb_strtoupper doesn't match String.toUpperCase Bug: T147646 Bug: T141723 Change-Id: Ic7a3d0cebbf4aec507db195ba8f587cecc1992aa --- diff --git a/jsduck.json b/jsduck.json index 5b183656ab..228c5c4696 100644 --- a/jsduck.json +++ b/jsduck.json @@ -9,6 +9,7 @@ "--warnings-exit-nonzero": true, "--external": "Blob,File,HTMLDocument,HTMLElement,HTMLIframeElement,HTMLInputElement,KeyboardEvent,MouseEvent,Node,Window,XMLDocument", "--output": "docs/js", + "--exclude": "resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js", "--": [ "maintenance/jsduck/external.js", "resources/src/mediawiki", diff --git a/resources/Resources.php b/resources/Resources.php index 52635f5a22..7a16e60ffe 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1194,7 +1194,10 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.Title' => [ - 'scripts' => 'resources/src/mediawiki/mediawiki.Title.js', + 'scripts' => [ + 'resources/src/mediawiki/mediawiki.Title.js', + 'resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js', + ], 'dependencies' => [ 'jquery.byteLength', 'mediawiki.util', diff --git a/resources/src/mediawiki/mediawiki.Title.js b/resources/src/mediawiki/mediawiki.Title.js index 9203e5e154..0e2af5060a 100644 --- a/resources/src/mediawiki/mediawiki.Title.js +++ b/resources/src/mediawiki/mediawiki.Title.js @@ -826,7 +826,9 @@ ) { return this.title; } - return this.title[ 0 ].toUpperCase() + this.title.slice( 1 ); + // PHP's strtoupper differs from String.toUpperCase in a number of cases + // Bug: T147646 + return mw.Title.phpCharToUpper( this.title[ 0 ] ) + this.title.slice( 1 ); }, /** diff --git a/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js b/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js new file mode 100644 index 0000000000..2b39c9ab29 --- /dev/null +++ b/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js @@ -0,0 +1,255 @@ +// This file can't be parsed by JSDuck due to . +// (It is excluded in jsduck.json.) +// ESLint suggests unquoting some object keys, which would render the file unparseable by Opera 12. +/* eslint-disable quote-props */ +( function ( mw ) { + var toUpperMapping = { + 'ß': 'ß', + 'ʼn': 'ʼn', + 'Dž': 'Dž', + 'dž': 'Dž', + 'Lj': 'Lj', + 'lj': 'Lj', + 'Nj': 'Nj', + 'nj': 'Nj', + 'ǰ': 'ǰ', + 'Dz': 'Dz', + 'dz': 'Dz', + 'ʝ': 'Ʝ', + 'ͅ': 'ͅ', + 'ΐ': 'ΐ', + 'ΰ': 'ΰ', + 'և': 'և', + 'ᏸ': 'Ᏸ', + 'ᏹ': 'Ᏹ', + 'ᏺ': 'Ᏺ', + 'ᏻ': 'Ᏻ', + 'ᏼ': 'Ᏼ', + 'ᏽ': 'Ᏽ', + 'ẖ': 'ẖ', + 'ẗ': 'ẗ', + 'ẘ': 'ẘ', + 'ẙ': 'ẙ', + 'ẚ': 'ẚ', + 'ὐ': 'ὐ', + 'ὒ': 'ὒ', + 'ὔ': 'ὔ', + 'ὖ': 'ὖ', + 'ᾀ': 'ᾈ', + 'ᾁ': 'ᾉ', + 'ᾂ': 'ᾊ', + 'ᾃ': 'ᾋ', + 'ᾄ': 'ᾌ', + 'ᾅ': 'ᾍ', + 'ᾆ': 'ᾎ', + 'ᾇ': 'ᾏ', + 'ᾈ': 'ᾈ', + 'ᾉ': 'ᾉ', + 'ᾊ': 'ᾊ', + 'ᾋ': 'ᾋ', + 'ᾌ': 'ᾌ', + 'ᾍ': 'ᾍ', + 'ᾎ': 'ᾎ', + 'ᾏ': 'ᾏ', + 'ᾐ': 'ᾘ', + 'ᾑ': 'ᾙ', + 'ᾒ': 'ᾚ', + 'ᾓ': 'ᾛ', + 'ᾔ': 'ᾜ', + 'ᾕ': 'ᾝ', + 'ᾖ': 'ᾞ', + 'ᾗ': 'ᾟ', + 'ᾘ': 'ᾘ', + 'ᾙ': 'ᾙ', + 'ᾚ': 'ᾚ', + 'ᾛ': 'ᾛ', + 'ᾜ': 'ᾜ', + 'ᾝ': 'ᾝ', + 'ᾞ': 'ᾞ', + 'ᾟ': 'ᾟ', + 'ᾠ': 'ᾨ', + 'ᾡ': 'ᾩ', + 'ᾢ': 'ᾪ', + 'ᾣ': 'ᾫ', + 'ᾤ': 'ᾬ', + 'ᾥ': 'ᾭ', + 'ᾦ': 'ᾮ', + 'ᾧ': 'ᾯ', + 'ᾨ': 'ᾨ', + 'ᾩ': 'ᾩ', + 'ᾪ': 'ᾪ', + 'ᾫ': 'ᾫ', + 'ᾬ': 'ᾬ', + 'ᾭ': 'ᾭ', + 'ᾮ': 'ᾮ', + 'ᾯ': 'ᾯ', + 'ᾲ': 'ᾲ', + 'ᾳ': 'ᾼ', + 'ᾴ': 'ᾴ', + 'ᾶ': 'ᾶ', + 'ᾷ': 'ᾷ', + 'ᾼ': 'ᾼ', + 'ῂ': 'ῂ', + 'ῃ': 'ῌ', + 'ῄ': 'ῄ', + 'ῆ': 'ῆ', + 'ῇ': 'ῇ', + 'ῌ': 'ῌ', + 'ῒ': 'ῒ', + 'ΐ': 'ΐ', + 'ῖ': 'ῖ', + 'ῗ': 'ῗ', + 'ῢ': 'ῢ', + 'ΰ': 'ΰ', + 'ῤ': 'ῤ', + 'ῦ': 'ῦ', + 'ῧ': 'ῧ', + 'ῲ': 'ῲ', + 'ῳ': 'ῼ', + 'ῴ': 'ῴ', + 'ῶ': 'ῶ', + 'ῷ': 'ῷ', + 'ῼ': 'ῼ', + 'ⅰ': 'ⅰ', + 'ⅱ': 'ⅱ', + 'ⅲ': 'ⅲ', + 'ⅳ': 'ⅳ', + 'ⅴ': 'ⅴ', + 'ⅵ': 'ⅵ', + 'ⅶ': 'ⅶ', + 'ⅷ': 'ⅷ', + 'ⅸ': 'ⅸ', + 'ⅹ': 'ⅹ', + 'ⅺ': 'ⅺ', + 'ⅻ': 'ⅻ', + 'ⅼ': 'ⅼ', + 'ⅽ': 'ⅽ', + 'ⅾ': 'ⅾ', + 'ⅿ': 'ⅿ', + 'ⓐ': 'ⓐ', + 'ⓑ': 'ⓑ', + 'ⓒ': 'ⓒ', + 'ⓓ': 'ⓓ', + 'ⓔ': 'ⓔ', + 'ⓕ': 'ⓕ', + 'ⓖ': 'ⓖ', + 'ⓗ': 'ⓗ', + 'ⓘ': 'ⓘ', + 'ⓙ': 'ⓙ', + 'ⓚ': 'ⓚ', + 'ⓛ': 'ⓛ', + 'ⓜ': 'ⓜ', + 'ⓝ': 'ⓝ', + 'ⓞ': 'ⓞ', + 'ⓟ': 'ⓟ', + 'ⓠ': 'ⓠ', + 'ⓡ': 'ⓡ', + 'ⓢ': 'ⓢ', + 'ⓣ': 'ⓣ', + 'ⓤ': 'ⓤ', + 'ⓥ': 'ⓥ', + 'ⓦ': 'ⓦ', + 'ⓧ': 'ⓧ', + 'ⓨ': 'ⓨ', + 'ⓩ': 'ⓩ', + 'ꞵ': 'Ꞵ', + 'ꞷ': 'Ꞷ', + 'ꭓ': 'Ꭓ', + 'ꭰ': 'Ꭰ', + 'ꭱ': 'Ꭱ', + 'ꭲ': 'Ꭲ', + 'ꭳ': 'Ꭳ', + 'ꭴ': 'Ꭴ', + 'ꭵ': 'Ꭵ', + 'ꭶ': 'Ꭶ', + 'ꭷ': 'Ꭷ', + 'ꭸ': 'Ꭸ', + 'ꭹ': 'Ꭹ', + 'ꭺ': 'Ꭺ', + 'ꭻ': 'Ꭻ', + 'ꭼ': 'Ꭼ', + 'ꭽ': 'Ꭽ', + 'ꭾ': 'Ꭾ', + 'ꭿ': 'Ꭿ', + 'ꮀ': 'Ꮀ', + 'ꮁ': 'Ꮁ', + 'ꮂ': 'Ꮂ', + 'ꮃ': 'Ꮃ', + 'ꮄ': 'Ꮄ', + 'ꮅ': 'Ꮅ', + 'ꮆ': 'Ꮆ', + 'ꮇ': 'Ꮇ', + 'ꮈ': 'Ꮈ', + 'ꮉ': 'Ꮉ', + 'ꮊ': 'Ꮊ', + 'ꮋ': 'Ꮋ', + 'ꮌ': 'Ꮌ', + 'ꮍ': 'Ꮍ', + 'ꮎ': 'Ꮎ', + 'ꮏ': 'Ꮏ', + 'ꮐ': 'Ꮐ', + 'ꮑ': 'Ꮑ', + 'ꮒ': 'Ꮒ', + 'ꮓ': 'Ꮓ', + 'ꮔ': 'Ꮔ', + 'ꮕ': 'Ꮕ', + 'ꮖ': 'Ꮖ', + 'ꮗ': 'Ꮗ', + 'ꮘ': 'Ꮘ', + 'ꮙ': 'Ꮙ', + 'ꮚ': 'Ꮚ', + 'ꮛ': 'Ꮛ', + 'ꮜ': 'Ꮜ', + 'ꮝ': 'Ꮝ', + 'ꮞ': 'Ꮞ', + 'ꮟ': 'Ꮟ', + 'ꮠ': 'Ꮠ', + 'ꮡ': 'Ꮡ', + 'ꮢ': 'Ꮢ', + 'ꮣ': 'Ꮣ', + 'ꮤ': 'Ꮤ', + 'ꮥ': 'Ꮥ', + 'ꮦ': 'Ꮦ', + 'ꮧ': 'Ꮧ', + 'ꮨ': 'Ꮨ', + 'ꮩ': 'Ꮩ', + 'ꮪ': 'Ꮪ', + 'ꮫ': 'Ꮫ', + 'ꮬ': 'Ꮬ', + 'ꮭ': 'Ꮭ', + 'ꮮ': 'Ꮮ', + 'ꮯ': 'Ꮯ', + 'ꮰ': 'Ꮰ', + 'ꮱ': 'Ꮱ', + 'ꮲ': 'Ꮲ', + 'ꮳ': 'Ꮳ', + 'ꮴ': 'Ꮴ', + 'ꮵ': 'Ꮵ', + 'ꮶ': 'Ꮶ', + 'ꮷ': 'Ꮷ', + 'ꮸ': 'Ꮸ', + 'ꮹ': 'Ꮹ', + 'ꮺ': 'Ꮺ', + 'ꮻ': 'Ꮻ', + 'ꮼ': 'Ꮼ', + 'ꮽ': 'Ꮽ', + 'ꮾ': 'Ꮾ', + 'ꮿ': 'Ꮿ', + 'ff': 'ff', + 'fi': 'fi', + 'fl': 'fl', + 'ffi': 'ffi', + 'ffl': 'ffl', + 'ſt': 'ſt', + 'st': 'st', + 'ﬓ': 'ﬓ', + 'ﬔ': 'ﬔ', + 'ﬕ': 'ﬕ', + 'ﬖ': 'ﬖ', + 'ﬗ': 'ﬗ' + }; + mw.Title.phpCharToUpper = function ( chr ) { + var mapped = toUpperMapping[ chr ]; + return mapped || chr.toUpperCase(); + }; +}( mediaWiki ) ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js index 910bcc1989..124c49f5b8 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js @@ -298,7 +298,7 @@ }, 'Throw error on empty string' ); } ); - QUnit.test( 'Case-sensivity', 3, function ( assert ) { + QUnit.test( 'Case-sensivity', 5, function ( assert ) { var title; // Default config @@ -307,6 +307,12 @@ title = new mw.Title( 'article' ); assert.equal( title.toString(), 'Article', 'Default config: No sensitive namespaces by default. First-letter becomes uppercase' ); + title = new mw.Title( 'ß' ); + assert.equal( title.toString(), 'ß', 'Uppercasing matches PHP behaviour (ß -> ß, not SS)' ); + + title = new mw.Title( 'dž (digraph)' ); + assert.equal( title.toString(), 'Dž_(digraph)', 'Uppercasing matches PHP behaviour (dž -> Dž, not DŽ)' ); + // $wgCapitalLinks = false; mw.config.set( 'wgCaseSensitiveNamespaces', [ 0, -2, 1, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15 ] );