https://www.mediawiki.org/wiki/Special:Code/MediaWiki/109233

Revision: 109233
Author:   gwicke
Date:     2012-01-17 22:29:26 +0000 (Tue, 17 Jan 2012)
Log Message:
-----------
Fix template argument expansion. 200 parser tests now passing.

Modified Paths:
--------------
    trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
    
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
    trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js
    trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
    trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt

Modified: 
trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js    
2012-01-17 22:16:44 UTC (rev 109232)
+++ trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js    
2012-01-17 22:29:26 UTC (rev 109233)
@@ -31,6 +31,8 @@
        // Register for template and templatearg tag tokens
        manager.addTransform( this.onTemplate.bind(this), 
                        this.rank, 'tag', 'template' );
+
+       // Template argument expansion
        manager.addTransform( this.onTemplateArg.bind(this), 
                        this.rank, 'tag', 'templatearg' );
 
@@ -73,7 +75,7 @@
                kv;
 
        var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]]
-                       .concat( token.orderedArgs );
+                       .concat( this._nameArgs( token.orderedArgs ) );
 
        //console.log( 'before AttributeTransformManager: ' + JSON.stringify( 
attributes, null, 2 ) );
        new AttributeTransformManager( 
@@ -92,6 +94,21 @@
        }
 };
 
+TemplateHandler.prototype._nameArgs = function ( orderedArgs ) {
+       var n = 1,
+               out = [];
+       for ( var i = 0, l = orderedArgs.length; i < l; i++ ) {
+               if ( ! orderedArgs[i][0].length ) {
+                       out.push( [[{ type: 'TEXT', value: n }], 
orderedArgs[i][1]]);
+                       n++;
+               } else {
+                       out.push( orderedArgs[i] );
+               }
+       }
+       //console.log( '_nameArgs: ' + JSON.stringify( out ) );
+       return out;
+};
+
 TemplateHandler.prototype._returnAttributes = function ( 
templateTokenTransformData, attributes ) {
        //console.log( 'TemplateHandler._returnAttributes: ' + 
JSON.stringify(attributes) );
        // Remove the target from the attributes
@@ -101,7 +118,7 @@
        if ( templateTokenTransformData.isAsync ) {
                this._expandTemplate ( templateTokenTransformData );
        }
-}
+};
 
 /**
  * Fetch, tokenize and token-transform a template after all arguments and the
@@ -144,9 +161,12 @@
        // 'text/wiki' input). 
        // Returned pipe (for now):
        // { first: tokenizer, last: AsyncTokenTransformManager }
+       //console.log( 'expanded args: ' + 
+       //              JSON.stringify( this.manager.env.KVtoHash( 
templateTokenTransformData.expandedArgs ) ) );
+
        this.inputPipeline = this.manager.newChildPipeline( 
                                this.manager.inputType || 'text/wiki', 
-                               templateTokenTransformData.expandedArgs,
+                               this.manager.env.KVtoHash( 
templateTokenTransformData.expandedArgs ),
                                templateTokenTransformData.target
                        );
 
@@ -299,20 +319,55 @@
  * Expand template arguments with tokens from the containing frame.
  */
 TemplateHandler.prototype.onTemplateArg = function ( token, cb, frame ) {
-       var argName = token.attribs[0][1]; // XXX: do this properly!
+       
+       var attributes = [[token.argname, token.defaultvalue]];
+
+       token.resultTokens = false;
+
+       new AttributeTransformManager( 
+                               this.manager, 
+                               this._returnArgAttributes.bind( this, token, 
cb, frame ) 
+                       ).process( attributes );
+
+       if ( token.resultTokens !== false ) {
+               // synchronous return
+               //console.log( 'synchronous attribute expand: ' + 
JSON.stringify( token.resultTokens ) );
+
+               return { tokens: token.resultTokens };
+       } else {
+               //console.log( 'asynchronous attribute expand: ' + 
JSON.stringify( token, null, 2 ) );
+               // asynchronous return
+               token.resultTokens = [];
+               return { async: true };
+       }
+};
+
+TemplateHandler.prototype._returnArgAttributes = function ( token, cb, frame, 
attributes ) {
+       //console.log( '_returnArgAttributes: ' + JSON.stringify( attributes ));
+       var argName = this.manager.env.tokensToString( attributes[0][0] ),
+               defaultValue = attributes[0][1],
+               res;
        if ( argName in frame.args ) {
                // return tokens for argument
-               return { tokens: frame.args[argName] };
+               //console.log( 'templateArg found: ' + argName + 
+               //              ' vs. ' + JSON.stringify( frame.args ) ); 
+               res = frame.args[argName];
        } else {
+               //console.log( 'templateArg not found: ' + argName + 
+               //              ' vs. ' + JSON.stringify( frame.args ) );
                if ( token.attribs.length > 1 ) {
-                       return token.attribs[1][1]; // default value, XXX: use 
key
+                       res = defaultValue;
                } else {
-                       return { token: { type: 'TEXT', value: '{{{' + argName 
+ '}}}' } };
+                       res = [{ type: 'TEXT', value: '{{{' + argName + '}}}' 
}];
                }
        }
+       if ( token.resultTokens !== false ) {
+               cb( res );
+       } else {
+               token.resultTokens =  res;
+       }
 };
 
-
 if (typeof module == "object") {
        module.exports.TemplateHandler = TemplateHandler;
 }

Modified: 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
===================================================================
--- 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js 
    2012-01-17 22:16:44 UTC (rev 109232)
+++ 
trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js 
    2012-01-17 22:29:26 UTC (rev 109233)
@@ -331,6 +331,7 @@
  * first stage of the pipeline, and 'last' pointing to the last stage.
  */
 AsyncTokenTransformManager.prototype.newChildPipeline = function ( inputType, 
args, title ) {
+       //console.log( 'newChildPipeline: ' + JSON.stringify( args ) );
        var pipe = this.childFactories.input( inputType, args );
 
        // now set up a few things on the child AsyncTokenTransformManager.
@@ -375,6 +376,7 @@
        this.accum = new TokenAccumulator(null);
        this.firstaccum = this.accum;
        this.prevToken = undefined;
+       //console.log( 'AsyncTokenTransformManager args ' + JSON.stringify( 
args ) );
        if ( ! args ) {
                this.args = {}; // no arguments at the top level
        } else {

Modified: 
trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js
===================================================================
--- 
trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js    
    2012-01-17 22:16:44 UTC (rev 109232)
+++ 
trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.environment.js    
    2012-01-17 22:29:26 UTC (rev 109233)
@@ -26,6 +26,18 @@
        return null;
 };
 
+MWParserEnvironment.prototype.KVtoHash = function ( kvs ) {
+       var res = {};
+       for ( var i = 0, l = kvs.length; i < l; i++ ) {
+               var kv = kvs[i],
+                       key = this.tokensToString( kv[0] );
+               if( res[key] === undefined ) {
+                       res[key] = kv[1];
+               }
+       }
+       //console.log( 'KVtoHash: ' + JSON.stringify( res ));
+       return res;
+}
 
 // Does this need separate UI/content inputs?
 MWParserEnvironment.prototype.formatNum = function( num ) {

Modified: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js    
2012-01-17 22:16:44 UTC (rev 109232)
+++ trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js    
2012-01-17 22:29:26 UTC (rev 109233)
@@ -130,8 +130,11 @@
 ParserPipeline.prototype.makeInputPipeline = function ( inputType, args ) {
        switch ( inputType ) {
                case 'text/wiki':
+                       //console.log( 'makeInputPipeline ' + JSON.stringify( 
args ) );
                        if ( this.pipelineCache['text/wiki'].input.length ) {
-                               return 
this.pipelineCache['text/wiki'].input.pop();
+                               var pipe = 
this.pipelineCache['text/wiki'].input.pop();
+                               pipe.last.args = args;
+                               return pipe;
                        } else {
                                var wikiTokenizer = new PegTokenizer();
 

Modified: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt
===================================================================
--- trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt 
2012-01-17 22:16:44 UTC (rev 109232)
+++ trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt 
2012-01-17 22:29:26 UTC (rev 109233)
@@ -538,7 +538,7 @@
 inline_element
   = //& { dp('inline_element enter' + input.substr(pos, 10)); return true; }
       & '<' ( comment / xmlish_tag )
-    / & '{' ( template / tplarg )
+    / & '{' ( tplarg / template )
     / & '[' ( wikilink / extlink )
     / & "'" quote
 
@@ -728,23 +728,28 @@
 
 template_param
   = name:template_param_name space* "=" space* c:template_param_text {
-      return [{ type: 'TEXT', value: name }, { type: 'TEXT', value: c }];
+      return [[{ type: 'TEXT', value: name }], flatten( c )];
   } / c:template_param_text {
-      return [[], { type: 'TEXT', value: c }];
+      return [[], flatten( c ) ];
   }
 
 tplarg 
-  = "{{{" name:link_target params:("|" p:template_param { return p })* "}}}" {
+  = "{{{" name:template_param_text params:("|" p:template_param { return p })* 
"}}}" {
+      name = flatten( name );
       var obj = { 
             type: 'SELFCLOSINGTAG', 
             name: 'templatearg', 
-            attribs: [['argname', name]]
+            attribs: [],
+            argname: name,
+            defaultvalue: []
       };
       if (params && params.length) {
           // HACK, not final.
           obj.attribs.push(['data-defaultvalue', params[0][1]]);
           obj.attribs.push(['data-json-args', JSON.stringify(params)]);
+          obj.defaultvalue = params[0][1];
       }
+      //console.log( 'tokenizer templatearg ' + JSON.stringify( obj ));
       return obj;
   }
 


_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to