vendor: 8,174 bytes, lines 1-310
1/*! 2 * jQuery Internationalization library 3 * 4 * Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar 5 * 6 * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do 7 * anything special to choose one license or the other and you don't have to 8 * notify anyone which license you are using. You are free to use 9 * UniversalLanguageSelector in commercial projects as long as the copyright 10 * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details. 11 * 12 * @licence GNU General Public Licence 2.0 or later 13 * @licence MIT License 14 */ 15 16( function ( $ ) { 17 'use strict'; 18 19 var MessageParser = function ( options ) { 20 this.options = $.extend( {}, $.i18n.parser.defaults, options ); 21 this.language = $.i18n.languages[ String.locale ] || $.i18n.languages[ 'default' ]; 22 this.emitter = $.i18n.parser.emitter; 23 }; 24 25 MessageParser.prototype = { 26 27 constructor: MessageParser, 28 29 simpleParse: function ( message, parameters ) { 30 return message.replace( /\$(\d+)/g, function ( str, match ) { 31 var index = parseInt( match, 10 ) - 1; 32 33 return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match; 34 } ); 35 }, 36 37 parse: function ( message, replacements ) { 38 if ( message.indexOf( '{{' ) < 0 ) { 39 return this.simpleParse( message, replacements ); 40 } 41 42 this.emitter.language = $.i18n.languages[ $.i18n().locale ] || 43 $.i18n.languages[ 'default' ]; 44 45 return this.emitter.emit( this.ast( message ), replacements ); 46 }, 47 48 ast: function ( message ) { 49 var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral, 50 regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar, 51 escapedOrRegularLiteral, templateContents, templateName, openTemplate, 52 closeTemplate, expression, paramExpression, result, 53 pos = 0; 54 55 // Try parsers until one works, if none work return null 56 function choice( parserSyntax ) { 57 return function () { 58 var i, result; 59 60 for ( i = 0; i < parserSyntax.length; i++ ) { 61 result = parserSyntax[ i ](); 62 63 if ( result !== null ) { 64 return result; 65 } 66 } 67 68 return null; 69 }; 70 } 71 72 // Try several parserSyntax-es in a row. 73 // All must succeed; otherwise, return null. 74 // This is the only eager one. 75 function sequence( parserSyntax ) { 76 var i, res, 77 originalPos = pos, 78 result = []; 79 80 for ( i = 0; i < parserSyntax.length; i++ ) { 81 res = parserSyntax[ i ](); 82 83 if ( res === null ) { 84 pos = originalPos; 85 86 return null; 87 } 88 89 result.push( res ); 90 } 91 92 return result; 93 } 94 95 // Run the same parser over and over until it fails. 96 // Must succeed a minimum of n times; otherwise, return null. 97 function nOrMore( n, p ) { 98 return function () { 99 var originalPos = pos, 100 result = [], 101 parsed = p(); 102 103 while ( parsed !== null ) { 104 result.push( parsed ); 105 parsed = p(); 106 } 107 108 if ( result.length < n ) { 109 pos = originalPos; 110 111 return null; 112 } 113 114 return result; 115 }; 116 } 117 118 // Helpers -- just make parserSyntax out of simpler JS builtin types 119 120 function makeStringParser( s ) { 121 var len = s.length; 122 123 return function () { 124 var result = null; 125 126 if ( message.slice( pos, pos + len ) === s ) { 127 result = s; 128 pos += len; 129 } 130 131 return result; 132 }; 133 } 134 135 function makeRegexParser( regex ) { 136 return function () { 137 var matches = message.slice( pos ).match( regex ); 138 139 if ( matches === null ) { 140 return null; 141 } 142 143 pos += matches[ 0 ].length; 144 145 return matches[ 0 ]; 146 }; 147 } 148 149 pipe = makeStringParser( '|' ); 150 colon = makeStringParser( ':' ); 151 backslash = makeStringParser( '\\' ); 152 anyCharacter = makeRegexParser( /^./ ); 153 dollar = makeStringParser( '$' ); 154 digits = makeRegexParser( /^\d+/ ); 155 regularLiteral = makeRegexParser( /^[^{}[\]$\\]/ ); 156 regularLiteralWithoutBar = makeRegexParser( /^[^{}[\]$\\|]/ ); 157 regularLiteralWithoutSpace = makeRegexParser( /^[^{}[\]$\s]/ ); 158 159 // There is a general pattern: 160 // parse a thing; 161 // if it worked, apply transform, 162 // otherwise return null. 163 // But using this as a combinator seems to cause problems 164 // when combined with nOrMore(). 165 // May be some scoping issue. 166 function transform( p, fn ) { 167 return function () { 168 var result = p(); 169 170 return result === null ? null : fn( result ); 171 }; 172 } 173 174 // Used to define "literals" within template parameters. The pipe 175 // character is the parameter delimeter, so by default 176 // it is not a literal in the parameter 177 function literalWithoutBar() { 178 var result = nOrMore( 1, escapedOrLiteralWithoutBar )(); 179 180 return result === null ? null : result.join( '' ); 181 } 182 183 function literal() { 184 var result = nOrMore( 1, escapedOrRegularLiteral )(); 185 186 return result === null ? null : result.join( '' ); 187 } 188 189 function escapedLiteral() { 190 var result = sequence( [ backslash, anyCharacter ] ); 191 192 return result === null ? null : result[ 1 ]; 193 } 194 195 choice( [ escapedLiteral, regularLiteralWithoutSpace ] ); 196 escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] ); 197 escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] ); 198 199 function replacement() { 200 var result = sequence( [ dollar, digits ] ); 201 202 if ( result === null ) { 203 return null; 204 } 205 206 return [ 'REPLACE', parseInt( result[ 1 ], 10 ) - 1 ]; 207 } 208 209 templateName = transform( 210 // see $wgLegalTitleChars 211 // not allowing : due to the need to catch "PLURAL:$1" 212 makeRegexParser( /^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/ ), 213 214 function ( result ) { 215 return result.toString(); 216 } 217 ); 218 219 function templateParam() { 220 var expr, 221 result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] ); 222 223 if ( result === null ) { 224 return null; 225 } 226 227 expr = result[ 1 ]; 228 229 // use a "CONCAT" operator if there are multiple nodes, 230 // otherwise return the first node, raw. 231 return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[ 0 ]; 232 } 233 234 function templateWithReplacement() { 235 var result = sequence( [ templateName, colon, replacement ] ); 236 237 return result === null ? null : [ result[ 0 ], result[ 2 ] ]; 238 } 239 240 function templateWithOutReplacement() { 241 var result = sequence( [ templateName, colon, paramExpression ] ); 242 243 return result === null ? null : [ result[ 0 ], result[ 2 ] ]; 244 } 245 246 templateContents = choice( [ 247 function () { 248 var res = sequence( [ 249 // templates can have placeholders for dynamic 250 // replacement eg: {{PLURAL:$1|one car|$1 cars}} 251 // or no placeholders eg: 252 // {{GRAMMAR:genitive|{{SITENAME}}} 253 choice( [ templateWithReplacement, templateWithOutReplacement ] ), 254 nOrMore( 0, templateParam ) 255 ] ); 256 257 return res === null ? null : res[ 0 ].concat( res[ 1 ] ); 258 }, 259 function () { 260 var res = sequence( [ templateName, nOrMore( 0, templateParam ) ] ); 261 262 if ( res === null ) { 263 return null; 264 } 265 266 return [ res[ 0 ] ].concat( res[ 1 ] ); 267 } 268 ] ); 269 270 openTemplate = makeStringParser( '{{' ); 271 closeTemplate = makeStringParser( '}}' ); 272 273 function template() { 274 var result = sequence( [ openTemplate, templateContents, closeTemplate ] ); 275 276 return result === null ? null : result[ 1 ]; 277 } 278 279 expression = choice( [ template, replacement, literal ] ); 280 paramExpression = choice( [ template, replacement, literalWithoutBar ] ); 281 282 function start() { 283 var result = nOrMore( 0, expression )(); 284 285 if ( result === null ) { 286 return null; 287 } 288 289 return [ 'CONCAT' ].concat( result ); 290 } 291 292 result = start(); 293 294 /* 295 * For success, the pos must have gotten to the end of the input 296 * and returned a non-null. 297 * n.b. This is part of language infrastructure, so we do not throw an 298 * internationalizable message. 299 */ 300 if ( result === null || pos !== message.length ) { 301 throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + message ); 302 } 303 304 return result; 305 } 306 307 }; 308 309 $.extend( $.i18n.parser, new MessageParser() ); 310}( jQuery ) );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.