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