Merge "(bug 41477) Add Language::isSupportedLanguage"
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.Title.js
index f7126cf..dad6021 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Relies on: mw.config (wgFormattedNamespaces, wgNamespaceIds, wgCaseSensitiveNamespaces), mw.util.wikiGetlink
  */
-( function( $ ) {
+( function ( mw, $ ) {
 
        /* Local space */
 
         * @param namespace {Number} (optional) Namespace id. If given, title will be taken as-is.
         * @return {Title} this
         */
-var    Title = function( title, namespace ) {
-               this._ns = 0; // integer namespace id
-               this._name = null; // name in canonical 'database' form
-               this._ext = null; // extension
+       function Title( title, namespace ) {
+               this.ns = 0; // integer namespace id
+               this.name = null; // name in canonical 'database' form
+               this.ext = null; // extension
 
                if ( arguments.length === 2 ) {
                        setNameAndExtension( this, title );
-                       this._ns = fixNsId( namespace );
+                       this.ns = fixNsId( namespace );
                } else if ( arguments.length === 1 ) {
                        setAll( this, title );
                }
                return this;
-       },
+       }
+
+var
+       /**
+        * Public methods (defined later)
+        */
+       fn,
 
        /**
         * Strip some illegal chars: control chars, colon, less than, greater than,
@@ -41,7 +47,7 @@ var   Title = function( title, namespace ) {
         * @param s {String}
         * @return {String}
         */
-       clean = function( s ) {
+       clean = function ( s ) {
                if ( s !== undefined ) {
                        return s.replace( /[\x00-\x1f\x23\x3c\x3e\x5b\x5d\x7b\x7c\x7d\x7f\s]+/g, '_' );
                }
@@ -63,14 +69,14 @@ var Title = function( title, namespace ) {
        /**
         * Sanitize name.
         */
-       fixName = function( s ) {
+       fixName = function ( s ) {
                return clean( $.trim( s ) );
        },
 
        /**
         * Sanitize name.
         */
-       fixExt = function( s ) {
+       fixExt = function ( s ) {
                return clean( s );
        },
 
@@ -79,7 +85,7 @@ var   Title = function( title, namespace ) {
         * @param id {Number} Namespace id.
         * @return {Number|Boolean} The id as-is or boolean false if invalid.
         */
-       fixNsId = function( id ) {
+       fixNsId = function ( id ) {
                // wgFormattedNamespaces is an object of *string* key-vals (ie. arr["0"] not arr[0] )
                var ns = mw.config.get( 'wgFormattedNamespaces' )[id.toString()];
 
@@ -98,9 +104,13 @@ var Title = function( title, namespace ) {
         * @param ns {String} Namespace name (case insensitive, leading/trailing space ignored).
         * @return {Number|Boolean} Namespace id or boolean false if unrecognized.
         */
-       getNsIdByName = function( ns ) {
-               // toLowerCase throws exception on null/undefined. Return early.
-               if ( ns == null ) {
+       getNsIdByName = function ( ns ) {
+               // Don't cast non-strings to strings, because null or undefined
+               // should not result in returning the id of a potential namespace
+               // called "Null:" (e.g. on nullwiki.example.org)
+               // Also, toLowerCase throws exception on null/undefined, because
+               // it is a String.prototype method.
+               if ( typeof ns !== 'string' ) {
                        return false;
                }
                ns = clean( $.trim( ns.toLowerCase() ) ); // Normalize
@@ -119,22 +129,22 @@ var       Title = function( title, namespace ) {
         * @param raw {String}
         * @return {mw.Title}
         */
-       setAll = function( title, s ) {
+       setAll = function ( title, s ) {
                // In normal browsers the match-array contains null/undefined if there's no match,
                // IE returns an empty string.
-               var     matches = s.match( /^(?:([^:]+):)?(.*?)(?:\.(\w{1,5}))?$/ ),
-                       ns_match = getNsIdByName( matches[1] );
+               var matches = s.match( /^(?:([^:]+):)?(.*?)(?:\.(\w+))?$/ ),
+                       nsMatch = getNsIdByName( matches[1] );
 
                // Namespace must be valid, and title must be a non-empty string.
-               if ( ns_match && typeof matches[2] === 'string' && matches[2] !== '' ) {
-                       title._ns = ns_match;
-                       title._name = fixName( matches[2] );
+               if ( nsMatch && typeof matches[2] === 'string' && matches[2] !== '' ) {
+                       title.ns = nsMatch;
+                       title.name = fixName( matches[2] );
                        if ( typeof matches[3] === 'string' && matches[3] !== '' ) {
-                               title._ext = fixExt( matches[3] );
+                               title.ext = fixExt( matches[3] );
                        }
                } else {
                        // Consistency with MediaWiki PHP: Unknown namespace -> fallback to main namespace.
-                       title._ns = 0;
+                       title.ns = 0;
                        setNameAndExtension( title, s );
                }
                return title;
@@ -147,16 +157,16 @@ var       Title = function( title, namespace ) {
         * @param raw {String}
         * @return {mw.Title}
         */
-       setNameAndExtension = function( title, raw ) {
+       setNameAndExtension = function ( title, raw ) {
                // In normal browsers the match-array contains null/undefined if there's no match,
                // IE returns an empty string.
-               var matches = raw.match( /^(?:)?(.*?)(?:\.(\w{1,5}))?$/ );
+               var matches = raw.match( /^(?:)?(.*?)(?:\.(\w+))?$/ );
 
                // Title must be a non-empty string.
                if ( typeof matches[1] === 'string' && matches[1] !== '' ) {
-                       title._name = fixName( matches[1] );
+                       title.name = fixName( matches[1] );
                        if ( typeof matches[2] === 'string' && matches[2] !== '' ) {
-                               title._ext = fixExt( matches[2] );
+                               title.ext = fixExt( matches[2] );
                        }
                } else {
                        throw new Error( 'mw.Title: Could not parse title "' + raw + '"' );
@@ -172,7 +182,7 @@ var Title = function( title, namespace ) {
         * @param title {mixed} prefixed db-key name (string) or instance of Title
         * @return {mixed} Boolean true/false if the information is available. Otherwise null.
         */
-       Title.exists = function( title ) {
+       Title.exists = function ( title ) {
                var type = $.type( title ), obj = Title.exist.pages, match;
                if ( type === 'string' ) {
                        match = obj[title];
@@ -198,12 +208,12 @@ var       Title = function( title, namespace ) {
                pages: {},
                /**
                 * @example Declare existing titles: Title.exist.set(['User:John_Doe', ...]);
-                * @example Declare titles inexisting: Title.exist.set(['File:Foo_bar.jpg', ...], false);
+                * @example Declare titles nonexistent: Title.exist.set(['File:Foo_bar.jpg', ...], false);
                 * @param titles {String|Array} Title(s) in strict prefixedDb title form.
                 * @param state {Boolean} (optional) State of the given titles. Defaults to true.
                 * @return {Boolean}
                 */
-               set: function( titles, state ) {
+               set: function ( titles, state ) {
                        titles = $.isArray( titles ) ? titles : [titles];
                        state = state === undefined ? true : !!state;
                        var pages = this.pages, i, len = titles.length;
@@ -216,15 +226,15 @@ var       Title = function( title, namespace ) {
 
        /* Public methods */
 
-       var fn = {
+       fn = {
                constructor: Title,
 
                /**
                 * Get the namespace number.
                 * @return {Number}
                 */
-               getNamespaceId: function(){
-                       return this._ns;
+               getNamespaceId: function (){
+                       return this.ns;
                },
 
                /**
@@ -232,19 +242,19 @@ var       Title = function( title, namespace ) {
                 * In NS_MAIN this is '', otherwise namespace name plus ':'
                 * @return {String}
                 */
-               getNamespacePrefix: function(){
-                       return mw.config.get( 'wgFormattedNamespaces' )[this._ns].replace( / /g, '_' ) + (this._ns === 0 ? '' : ':');
+               getNamespacePrefix: function (){
+                       return mw.config.get( 'wgFormattedNamespaces' )[this.ns].replace( / /g, '_' ) + (this.ns === 0 ? '' : ':');
                },
 
                /**
                 * The name, like "Foo_bar"
                 * @return {String}
                 */
-               getName: function() {
-                       if ( $.inArray( this._ns, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ) {
-                               return this._name;
+               getName: function () {
+                       if ( $.inArray( this.ns, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ) {
+                               return this.name;
                        } else {
-                               return $.ucFirst( this._name );
+                               return $.ucFirst( this.name );
                        }
                },
 
@@ -252,7 +262,7 @@ var Title = function( title, namespace ) {
                 * The name, like "Foo bar"
                 * @return {String}
                 */
-               getNameText: function() {
+               getNameText: function () {
                        return text( this.getName() );
                },
 
@@ -260,7 +270,7 @@ var Title = function( title, namespace ) {
                 * Get full name in prefixed DB form, like File:Foo_bar.jpg,
                 * most useful for API calls, anything that must identify the "title".
                 */
-               getPrefixedDb: function() {
+               getPrefixedDb: function () {
                        return this.getNamespacePrefix() + this.getMain();
                },
 
@@ -268,7 +278,7 @@ var Title = function( title, namespace ) {
                 * Get full name in text form, like "File:Foo bar.jpg".
                 * @return {String}
                 */
-               getPrefixedText: function() {
+               getPrefixedText: function () {
                        return text( this.getPrefixedDb() );
                },
 
@@ -276,7 +286,7 @@ var Title = function( title, namespace ) {
                 * The main title (without namespace), like "Foo_bar.jpg"
                 * @return {String}
                 */
-               getMain: function() {
+               getMain: function () {
                        return this.getName() + this.getDotExtension();
                },
 
@@ -284,7 +294,7 @@ var Title = function( title, namespace ) {
                 * The "text" form, like "Foo bar.jpg"
                 * @return {String}
                 */
-               getMainText: function() {
+               getMainText: function () {
                        return text( this.getMain() );
                },
 
@@ -292,23 +302,23 @@ var       Title = function( title, namespace ) {
                 * Get the extension (returns null if there was none)
                 * @return {String|null} extension
                 */
-               getExtension: function() {
-                       return this._ext;
+               getExtension: function () {
+                       return this.ext;
                },
 
                /**
                 * Convenience method: return string like ".jpg", or "" if no extension
                 * @return {String}
                 */
-               getDotExtension: function() {
-                       return this._ext === null ? '' : '.' + this._ext;
+               getDotExtension: function () {
+                       return this.ext === null ? '' : '.' + this.ext;
                },
 
                /**
                 * Return the URL to this title
                 * @return {String}
                 */
-               getUrl: function() {
+               getUrl: function () {
                        return mw.util.wikiGetlink( this.toString() );
                },
 
@@ -316,7 +326,7 @@ var Title = function( title, namespace ) {
                 * Whether this title exists on the wiki.
                 * @return {mixed} Boolean true/false if the information is available. Otherwise null.
                 */
-               exists: function() {
+               exists: function () {
                        return Title.exists( this );
                }
        };
@@ -331,4 +341,4 @@ var Title = function( title, namespace ) {
        // Expose
        mw.Title = Title;
 
-})(jQuery);
+}( mediaWiki, jQuery ) );