From ffd5957f08f8fea4548ebdc9cd11ebbb113707f7 Mon Sep 17 00:00:00 2001 From: Michael Dale Date: Mon, 5 Oct 2009 09:39:26 +0000 Subject: [PATCH] * more language updates * PLURAL partially supported * more test refinement for testing js vs mediaWiki transform --- .../libAddMedia/mvBaseUploadInterface.js | 2 +- js2/mwEmbed/mv_embed.js | 378 +++++++++++++----- js2/mwEmbed/tests/testLang.html | 53 ++- js2/mwEmbed/tests/testLangEn.js | 3 +- 4 files changed, 319 insertions(+), 117 deletions(-) diff --git a/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js b/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js index 2f129e4595..1955f0f3f6 100644 --- a/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js +++ b/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js @@ -211,7 +211,7 @@ mvBaseUploadInterface.prototype = { _this.upload_mode == 'api' && ( $j('#wpSourceTypeFile').length == 0 || $j('#wpSourceTypeFile').get(0).checked ) ){ - //@@TODO check for sendAsBinnary to support firefox 3.5 progress + //@@TODO check for sendAsBinnary to support firefox 3.5 progress on upload //set the form target to iframe target: _this.iframeId = 'f_' + ($j('iframe').length + 1); diff --git a/js2/mwEmbed/mv_embed.js b/js2/mwEmbed/mv_embed.js index 131e55391f..1942b64821 100644 --- a/js2/mwEmbed/mv_embed.js +++ b/js2/mwEmbed/mv_embed.js @@ -70,7 +70,7 @@ parseUri.options = { // For use when mv_embed with script-loader is in the root MediaWiki path var mediaWiki_mvEmbed_path = 'js2/mwEmbed/'; -var _global = this; // Global obj +var _global = this; // Global obj (depreciate use window) /* * setup the empty global $mw object @@ -109,10 +109,11 @@ if( !mv_embed_path ) { * Setup the lang object */ var gMsg = {}; - var gRuleSet = {}; + var gRuleSet = {}; + /** * loadGM function - * Loads a set of json messages into the lang object. + * Loads a set of json messages into the lng object. * * @param json msgSet The set of msgs to be loaded */ @@ -144,89 +145,50 @@ if( !mv_embed_path ) { * @param [mixed] args An array of replacement strings * @return string */ - $.lang.gM = function( key , args ) { - var supportedMagicLang = ['PLURAL']; - - if ( gMsg[ key ] ) { - var ms = ''; - //get the messege string: - ms = gMsg[ key ]; - - //replace values - if( typeof args == 'object' || typeof args == 'array' ) { - for( var v in args ) { - // Message test replace arguments start at 1 instead of zero: - var rep = '\$'+ ( parseInt(v) + 1 ); - ms = ms.replace( rep, args[v] ); - } - } else if( typeof args =='string' || typeof args =='number' ) { - ms = ms.replace(/\$1/, args); - } - - //a quick check to see if we need to send the msg via the 'parser' - //(we can add more detailed check once we suport more wiki syntax) - if(ms.indexOf('{{')==-1) - return ms; - - //send the msg key through the parser - pObj = $.parse( ms ); - //return the transformed msg - return pObj.getHTML(); - - } else { - // Missing key placeholder - return '<' + key + '>'; - } + $.lang.gM = function( key , args ) { + if(! gMsg[ key ]) + return '<' + key + '>';// Missing key placeholder + + //swap in the arg values + var ms = $.lang.gMsgSwap( key, args); + //a quick check to see if we need to send the msg via the 'parser' + //(we can add more detailed check once we suport more wiki syntax) + if(ms.indexOf('{{')==-1) + return ms; + + //make sure we have the lagMagic setup: + $.lang.magicSetup(); + //send the msg key through the parser + pObj = $.parser.pNew( ms ); + //return the transformed msg + return pObj.getHTML(); } /** - * Process a special language template (ie PLURAL ) + * gMsgSwap + * + * @param string key The msg key as set by loadGm + * @param [mixed] args An array or string to be replaced + * @return string */ - $.lang.procLangTemp = function( tObj ){ - - /* local lang templates: */ - function procPLURAL(){ - //Plural matchRuleTest - function matchRuleTest(cRule, val){ - js_log("matchRuleTest:: " + typeof cRule + ' ' + cRule + ' == ' + val ); - //check for simple cRule type: - if( typeof cRule == 'number'){ - return ( parseInt( val ) == parseInt( cRule) ); - } - } - //maps a given rule Index to template params: - function getTempParamFromRuleInx( ruleInx ){ - //in general this is a one to one mapping: - - js_log('getTempParamFromRuleInx: ruleInx: ' + ruleInx + ' tempParamLength ' + tObj.param.length ); - var cat = tObj; - debugger; - return tObj.param[ ruleInx ]; - } - - //setup shortcuts - var rs = gRuleSet['PLURAL']; - var val = tObj.val; - for(var ruleInx in rs){ - cRule = rs[ruleInx]; - if( matchRuleTest( cRule, val )){ - js_log("matched rule: " + ruleInx ); - return getTempParamFromRuleInx( ruleInx ); - } - } - js_log('no match found for: ' + val + ' using last/other : ' + tObj.param [ tObj.param.length -1 ] ); - //return the last /"other" template param - return tObj.param [ tObj.param.length -1 ]; - } + $.lang.gMsgSwap = function( key , args ){ + if(! gMsg[ key ]) + return '<' + key + '>';// Missing key placeholder + //get the messege string: + ms = gMsg[ key ]; - /* - * Master rule switch statement - */ - switch( tObj.n ){ - case 'PLURAL': - return procPLURAL(); - break; + //replace values + if( typeof args == 'object' || typeof args == 'array' ) { + for( var v in args ) { + // Message test replace arguments start at 1 instead of zero: + var rep = '\$'+ ( parseInt(v) + 1 ); + ms = ms.replace( rep, args[v] ); + } + } else if( typeof args =='string' || typeof args =='number' ) { + ms = ms.replace(/\$1/g, args); } + return ms; } + /** * gMsgNoTrans * @@ -239,6 +201,63 @@ if( !mv_embed_path ) { // Missing key placeholder return '<' + key + '>'; } + /** + * Add Supported Magic Words to parser + */ + //set the setupflag to false: + $.lang.doneSetup=false; + $.lang.magicSetup = function(){ + if(!$.lang.doneSetup){ + $.parser.addMagic ( { + 'PLURAL' : $.lang.procPLURAL + }) + + $.lang.doneSetup = true; + } + + } + /** + * Process the PLURAL special language template key: + */ + $.lang.procPLURAL = function( tObj ){ + //setup shortcuts + // (gRuleSet is loaded from script-loader to contains local ruleset) + var rs = gRuleSet['PLURAL']; + + /* + * Plural matchRuleTest + */ + function matchRuleTest(cRule, val){ + js_log("matchRuleTest:: " + typeof cRule + ' ' + cRule + ' == ' + val ); + //check for simple cRule type: + if( typeof cRule == 'number'){ + return ( parseInt( val ) == parseInt( cRule) ); + } + } + /** + * Maps a given rule Index to template params: + * + * @param + */ + function getTempParamFromRuleInx( ruleInx ){ + //var naturalOrder = ['zero', 'one', 'two', 'few', 'many', 'other']; + //js_log('getTempParamFromRuleInx: ruleInx: ' + ruleInx + ' tempParamLength ' + tObj.param.length ); + return tObj.param[ ruleInx ]; + } + var rCount=0 + //run the acutal rule lookup: + for(var ruleInx in rs){ + cRule = rs[ruleInx]; + if( matchRuleTest( cRule, tObj.arg ) ){ + js_log("matched rule: " + ruleInx ); + return getTempParamFromRuleInx( rCount ); + } + rCount ++; + } + js_log('no match found for: ' + tObj.arg + ' using last/other : ' + tObj.param [ tObj.param.length -1 ] ); + //return the last /"other" template param + return tObj.param [ tObj.param.length -1 ]; + } /** * gMsgLoadRemote loads remote msg strings @@ -310,60 +329,203 @@ if( !mv_embed_path ) { var size = Math.round( size * p ) / p; //@@todo we need a formatNum and we need to request some special packaged info to deal with that case. return gM( msg , size ); - } + }; /** * MediaWiki wikitext "Parser" * * This is not feature complete but we need a way to get at template properties - * - * Template parsing is based in part on Magnus initial version: en:User:Magnus_Manske/tmpl.js + * * * @param wikiText the wikitext to be parsed * @return parserObj returns a parser object that has methods for getting at * things you would want - */ - $.parse = function( wikiText, opt ){ + */ + $.parser = {}; + var pMagicSet = {}; + /** + * parser addMagic + * + * lets you add a set of magic keys and associated callback funcions + * callback: @param ( Object Template ) + * callback: @return the transformed template output + * + * @param object magicSet key:callback + */ + $.parser.addMagic = function( magicSet ){ + for(var i in magicSet) + pMagicSet[ i ] = magicSet[i]; + } + + //actual parse call (returns parser object) + $.parser.pNew = function( wikiText, opt ){ var parseObj = function( wikiText, opt){ return this.init( wikiText, opt ) } parseObj.prototype = { - pObj : {}, //the parser object that stores the parsed element structure + //the wikiText "DOM"... stores the parsed wikiText structure + //wtDOM : {}, (not yet supported ) + pOut : '', //the parser output string container init :function( wikiText ){ + this.wikiText = wikiText; + }, + updateText : function( wikiText ){ this.wikiText = wikiText; - this.parse(); + //invalidate the output (will force a reparse) + this.pOut = ''; }, - parse : function(){ - //basic parser stores wikiText structure in pObj + parse : function(){ + this.pObj = {}; + this.pObj.tmpl = new Array(); + + //refrences for swap key + this.pObj.tmpl_text = new Array(); + this.pObj.tmpl_key = new Array(); + this.pObj.tmpl_ns = '' ; // wikiText with place-holder + + //get templates losly based on Magnus_Manske/tmpl.js code: + var tcnt = 0 ; + var ts = '' ; + var curt = 0 ; + var schar = 0; + for ( var a = 0 ; a < this.wikiText.length ; a++ ) { + if ( this.wikiText[a] == '{' && this.wikiText[a+1] == '{' ) { + //set the start index if the outer most template: + if( tcnt == 0 ) + schar = a; + + tcnt++ ; + a++ ; + if ( tcnt > 1 ) ts += '{{' ; + } else if ( this.wikiText[a] == '}' && this.wikiText[a+1] == '}' ) { + if ( tcnt > 1 ) ts += '}}' ; + if ( tcnt > 0 ) tcnt-- ; + if ( tcnt == 0 ) { + curt++ ; + //@@todo handle type stuff + tObj = { + "s" : schar, + "e" : a + 2, + "iText" : ts + } + //Get template name: + tname = ts.split('\|').shift() ; + tname = tname.split('\{').shift() ; + tname = tname.replace( /^\s+|\s+$/g, "" ); //trim + //check for arguments: + if( tname.split(':').length == 1 ){ + tObj["name"] = tname + }else{ + tObj["name"] = tname.split(':').shift(); + tObj["arg"] = tname.split(':').pop(); + } + + //set template params + //get all the params (not including the name) + var cat = ts; + + var pSet = ts.split('\|'); + pSet.splice(0,1); + if( pSet.length ){ + tObj.param = new Array(); + for(var pInx in pSet){ + var tStr = pSet[ pInx ]; + for(var b=0 ; b < tStr.length ; b++){ + if(tStr[b] == '=' && b>0 && bhtml-ish output without re-parsing anything + */ getHTML : function(){ - //copy the wikiText into the output (where we will do replaces) - this.pOut = this.wikiText; - this.doMagicExpand(); + //wikiText updates should invalidate pOut + if( this.pOut == ''){ + this.parse(); + }else{ + return this.pOut; + } + + //build output from swapable index: (could be moved to 'parse') + tSet = this.templates(); + if( !tSet.length ) + return this.wikiText; + //return:: + var cInx = 0; + for(var i in tSet){ + tObj = tSet[i]; + //check start point (fill from source to that point) + this.pOut+= this.wikiText.substring(cInx, tObj.s ); + //output the transformed template + this.pOut+= tObj.oText; + cInx = tObj.e; + } + if( tObj.e < this.wikiText.length) + this.pOut += this.wikiText.substring( tObj.e ); + return this.pOut; } }; diff --git a/js2/mwEmbed/tests/testLang.html b/js2/mwEmbed/tests/testLang.html index b228e34049..8b13283b38 100644 --- a/js2/mwEmbed/tests/testLang.html +++ b/js2/mwEmbed/tests/testLang.html @@ -13,8 +13,11 @@ td{ js2AddOnloadHook( function(){ //build table output: var o = ''; - var msgTestSet = [ 'test_plural_msg', 'undelete_short' ]; - var testNumberSet = [ 0, 1, 2, 5, 21, 22, 30 ]; + var msgTestSet = [ 'test_plural_msg', 'undelete_short', 'category-subcat-count' ]; + var testNumberSet = [ 0, 1, 2, 5, 21, 30 ]; + var passTest=0; + var failTest=0; + var testCount=0; //now for each langage msg: $j.each(msgTestSet, function(inx, mKey){ //output table names: @@ -28,18 +31,54 @@ js2AddOnloadHook( function(){ //for each number value for(var i in testNumberSet){ - var numVal = testNumberSet[i]; + var numVal = testNumberSet[i]; o+=''+ '' + '' + '' + - ''; + ''; //show mw col: if( mKey.substr(0, 5) == 'test_' ){ o+=''; }else{ - o+=''; - //get transform from mw (& compare and highlight) + o+=''; + + //get transform from mw (& compare and highlight) + function doPopWmMsg(mKey, numVal){ + testCount++; + $j('#score_card').html('Running Tests 0% done'); + do_api_req({ + 'data': { + 'action':'parse', + 'text': $mw.lang.gMsgSwap( mKey, numVal) + }, + 'url' : '../../../api.php' + }, function( data ) { + js_log("got data::" + data.parse.text['*']); + var t = '#'+ mKey + '_'+ numVal; + if(data.parse && data.parse.text && data.parse.text['*']){ + $j(t).html( data.parse.text['*'] ); + //just get the part in the

to compare with js version + if( $j.trim( $j(t + ' p').html() ) != $j.trim( $j(t + '_js').html() ) ){ + $j(t).css('color', 'red'); + failTest++; + }else{ + $j(t).css('color', 'green'); + passTest++; + } + var perc = ( failTest + passTest ) / testCount + if( perc != 1){ + $j('#perc_done').html( Math.round(perc*1000)/1000 + '%'); + }else{ + $j('#score_card').html( "Passed: " + passTest + ' Failed:' +failTest); + } + }else{ + $t.html(' error '); + } + }); + }; + //pop off an anonymous function call: + doPopWmMsg(mKey, numVal); } o+='

'; } @@ -54,7 +93,7 @@ js2AddOnloadHook( function(){

Test Javascript plural msg transformations

- +
diff --git a/js2/mwEmbed/tests/testLangEn.js b/js2/mwEmbed/tests/testLangEn.js index d970ea6ef2..3a5255abff 100644 --- a/js2/mwEmbed/tests/testLangEn.js +++ b/js2/mwEmbed/tests/testLangEn.js @@ -6,7 +6,8 @@ loadGM({ //test msg with english words to see whats going on 'test_plural_msg' : '{{PLURAL:$1|one|other}}', //sample real world msgs: - 'undelete_short' : 'Undelete {{PLURAL:$1|one edit|$1 edits}}' + 'undelete_short' : 'Undelete {{PLURAL:$1|one edit|$1 edits}}', + 'category-subcat-count' : "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}" }); $mw.lang.loadRS({ -- 2.20.1
' + numVal + '' + mKey + '' + $mw.lang.gMsgNoTrans( mKey ) + '' + $mw.lang.gM( mKey, numVal ) + '' + $mw.lang.gM( mKey, numVal ) + ' (test msg) loading...loading...