Merge "(bug 41477) Add Language::isSupportedLanguage"
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.jqueryMsg.js
index 6e2d3b4..934e906 100644 (file)
                 */
                return function () {
                        var $target = this.empty();
+                       // TODO: Simply $target.append( failableParserFn( arguments ).contents() )
+                       // or Simply $target.append( failableParserFn( arguments ) )
                        $.each( failableParserFn( arguments ).contents(), function ( i, node ) {
                                $target.append( node );
                        } );
                                regularLiteral, regularLiteralWithoutBar, regularLiteralWithoutSpace, backslash, anyCharacter,
                                escapedOrLiteralWithoutSpace, escapedOrLiteralWithoutBar, escapedOrRegularLiteral,
                                whitespace, dollar, digits,
-                               openExtlink, closeExtlink, openLink, closeLink, templateName, pipe, colon,
+                               openExtlink, closeExtlink, wikilinkPage, wikilinkContents, openLink, closeLink, templateName, pipe, colon,
                                templateContents, openTemplate, closeTemplate,
                                nonWhitespaceExpression, paramExpression, expression, result;
 
                                 var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
                                 return result === null ? null : result.join('');
                        }
+
+                       // Used for wikilink page names.  Like literalWithoutBar, but
+                       // without allowing escapes.
+                       function unescapedLiteralWithoutBar() {
+                               var result = nOrMore( 1, regularLiteralWithoutBar )();
+                               return result === null ? null : result.join('');
+                       }
+
                        function literal() {
                                 var result = nOrMore( 1, escapedOrRegularLiteral )();
                                 return result === null ? null : result.join('');
                        }
                        openLink = makeStringParser( '[[' );
                        closeLink = makeStringParser( ']]' );
+                       pipe = makeStringParser( '|' );
+
+                       function template() {
+                               var result = sequence( [
+                                       openTemplate,
+                                       templateContents,
+                                       closeTemplate
+                               ] );
+                               return result === null ? null : result[1];
+                       }
+
+                       wikilinkPage = choice( [
+                               unescapedLiteralWithoutBar,
+                               template
+                       ] );
+
+                       function pipedWikilink() {
+                               var result = sequence( [
+                                       wikilinkPage,
+                                       pipe,
+                                       expression
+                               ] );
+                               return result === null ? null : [ result[0], result[2] ];
+                       }
+
+                       wikilinkContents = choice( [
+                               pipedWikilink,
+                               wikilinkPage // unpiped link
+                       ] );
+
                        function link() {
-                               var result, parsedResult;
+                               var result, parsedResult, parsedLinkContents;
                                result = null;
+
                                parsedResult = sequence( [
                                        openLink,
-                                       expression,
+                                       wikilinkContents,
                                        closeLink
                                ] );
                                if ( parsedResult !== null ) {
-                                        result = [ 'WLINK', parsedResult[1] ];
+                                       parsedLinkContents = parsedResult[1];
+                                       result = [ 'WLINK' ].concat( parsedLinkContents );
                                }
                                return result;
                        }
                                // use a CONCAT operator if there are multiple nodes, otherwise return the first node, raw.
                                return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[0];
                        }
-                       pipe = makeStringParser( '|' );
+
                        function templateWithReplacement() {
                                var result = sequence( [
                                        templateName,
                        ] );
                        openTemplate = makeStringParser('{{');
                        closeTemplate = makeStringParser('}}');
-                       function template() {
-                               var result = sequence( [
-                                       openTemplate,
-                                       templateContents,
-                                       closeTemplate
-                               ] );
-                               return result === null ? null : result[1];
-                       }
                        nonWhitespaceExpression = choice( [
                                template,
                                link,
                                replacement,
                                literalWithoutBar
                        ] );
+
                        expression = choice( [
                                template,
                                link,
                                replacement,
                                literal
                        ] );
+
                        function start() {
                                var result = nOrMore( 0, expression )();
                                if ( result === null ) {
                                                $span.append( childNode );
                                        } );
                                } else {
-                                       // strings, integers, anything else
-                                       $span.append( node );
+                                       // Let jQuery append nodes, arrays of nodes and jQuery objects
+                                       // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
+                                       $span.append( $.type( node ) === 'object' ? node : document.createTextNode( node ) );
                                }
                        } );
                        return $span;
                 * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ].
                 * if the specified parameter is not found return the same string
                 * (e.g. "$99" -> parameter 98 -> not found -> return "$99" )
-                * TODO throw error if nodes.length > 1 ?
+                * TODO: Throw error if nodes.length > 1 ?
                 * @param {Array} of one element, integer, n >= 0
                 * @return {String} replacement
                 */
                        var index = parseInt( nodes[0], 10 );
 
                        if ( index < replacements.length ) {
-                               if ( typeof arg === 'string' ) {
-                                       // replacement is a string, escape it
-                                       return mw.html.escape( replacements[index] );
-                               } else {
-                                       // replacement is no string, don't touch!
-                                       return replacements[index];
-                               }
+                               return replacements[index];
                        } else {
                                // index not found, fallback to displaying variable
                                return '$' + ( index + 1 );
 
                /**
                 * Transform wiki-link
-                * TODO unimplemented
+                *
+                * TODO:
+                * It only handles basic cases, either no pipe, or a pipe with an explicit
+                * anchor.
+                *
+                * It does not attempt to handle features like the pipe trick.
+                * However, the pipe trick should usually not be present in wikitext retrieved
+                * from the server, since the replacement is done at save time.
+                * It may, though, if the wikitext appears in extension-controlled content.
+                *
                 * @param nodes
                 */
-               wlink: function () {
-                       return 'unimplemented';
+               wlink: function ( nodes ) {
+                       var page, anchor, url;
+
+                       page = nodes[0];
+                       url = mw.util.wikiGetlink( page );
+
+                       // [[Some Page]] or [[Namespace:Some Page]]
+                       if ( nodes.length === 1 ) {
+                               anchor = page;
+                       }
+
+                       /*
+                        * [[Some Page|anchor text]] or
+                        * [[Namespace:Some Page|anchor]
+                        */
+                       else {
+                               anchor = nodes[1];
+                       }
+
+                       return $( '<a />' ).attr( {
+                               title: page,
+                               href: url
+                       } ).text( anchor );
                },
 
                /**
                        var form = nodes[0],
                                word = nodes[1];
                        return word && form && this.language.convertGrammar( word, form );
+               },
+
+               /**
+                * Tranform parsed structure into a int: (interface language) message include
+                * Invoked by putting {{MediaWiki:othermessage}} into a message
+                * @param {Array} of nodes
+                * @return {string} Other message
+                */
+               int: function ( nodes ) {
+                       return mw.jqueryMsg.getMessageFunction()( nodes[0].toLowerCase() );
+               },
+
+               /**
+                * Takes an unformatted number (arab, no group separators and . as decimal separator)
+                * and outputs it in the localized digit script and formatted with decimal
+                * separator, according to the current language
+                * @param {Array} of nodes
+                * @return {Number|String} formatted number
+                */
+               formatnum: function ( nodes ) {
+                       var isInteger = ( nodes[1] && nodes[1] === 'R' ) ? true : false,
+                               number = nodes[0];
+
+                       return this.language.convertNumber( number, isInteger );
                }
        };
        // Deprecated! don't rely on gM existing.
                // Caching is somewhat problematic, because we do need different message functions for different maps, so
                // we'd have to cache the parser as a member of this.map, which sounds a bit ugly.
                // Do not use mw.jqueryMsg unless required
-               if ( this.map.get( this.key ).indexOf( '{{' ) < 0 ) {
+               if ( !/\{\{|\[/.test(this.map.get( this.key ) ) ) {
                        // Fall back to mw.msg's simple parser
                        return oldParser.apply( this );
                }