2012-01-06 14:30:55 +00:00
|
|
|
/**
|
2012-01-09 19:33:49 +00:00
|
|
|
* Template and template argument handling, first cut.
|
|
|
|
*
|
|
|
|
* AsyncTokenTransformManager objects provide preprocessor-frame-like
|
|
|
|
* functionality once template args etc are fully expanded, and isolate
|
|
|
|
* individual transforms from concurrency issues. Template argument expansion
|
|
|
|
* is performed using a structure managed in this extension.
|
2012-01-06 14:30:55 +00:00
|
|
|
*
|
|
|
|
* @author Gabriel Wicke <gwicke@wikimedia.org>
|
2012-01-06 17:19:14 +00:00
|
|
|
* @author Brion Vibber <brion@wikimedia.org>
|
2012-01-06 14:30:55 +00:00
|
|
|
*/
|
2012-01-11 19:48:49 +00:00
|
|
|
var $ = require('jquery'),
|
2012-01-18 19:38:32 +00:00
|
|
|
request = require('request'),
|
|
|
|
qs = require('querystring'),
|
|
|
|
AttributeTransformManager = require('./mediawiki.TokenTransformManager.js')
|
|
|
|
.AttributeTransformManager;
|
2012-01-06 17:19:14 +00:00
|
|
|
|
2012-01-06 14:30:55 +00:00
|
|
|
|
2012-01-11 19:48:49 +00:00
|
|
|
function TemplateHandler ( manager ) {
|
2012-01-06 14:30:55 +00:00
|
|
|
this.reset();
|
2012-01-11 19:48:49 +00:00
|
|
|
this.register( manager );
|
2012-01-06 14:30:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-17 20:01:21 +00:00
|
|
|
TemplateHandler.prototype.reset = function ( token ) {
|
2012-01-13 18:48:25 +00:00
|
|
|
this.resultTokens = [];
|
2012-01-17 20:01:21 +00:00
|
|
|
return {token: token};
|
2012-01-06 14:30:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// constants
|
|
|
|
TemplateHandler.prototype.rank = 1.1;
|
|
|
|
|
2012-01-09 17:49:16 +00:00
|
|
|
TemplateHandler.prototype.register = function ( manager ) {
|
|
|
|
this.manager = manager;
|
2012-01-06 14:30:55 +00:00
|
|
|
// Register for template and templatearg tag tokens
|
2012-01-09 17:49:16 +00:00
|
|
|
manager.addTransform( this.onTemplate.bind(this),
|
2012-01-06 14:30:55 +00:00
|
|
|
this.rank, 'tag', 'template' );
|
2012-01-17 22:29:26 +00:00
|
|
|
|
|
|
|
// Template argument expansion
|
2012-01-09 17:49:16 +00:00
|
|
|
manager.addTransform( this.onTemplateArg.bind(this),
|
2012-01-06 14:30:55 +00:00
|
|
|
this.rank, 'tag', 'templatearg' );
|
|
|
|
|
|
|
|
// Reset internal state when the parser pipeline is done
|
2012-01-17 20:01:21 +00:00
|
|
|
//manager.addTransform( this.reset.bind(this),
|
|
|
|
// this.rank, 'end' );
|
2012-01-06 14:30:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Main template token handler
|
|
|
|
*
|
|
|
|
* Expands target and arguments (both keys and values) and either directly
|
|
|
|
* calls or sets up the callback to _expandTemplate, which then fetches and
|
|
|
|
* processes the template.
|
|
|
|
*/
|
2012-01-09 17:49:16 +00:00
|
|
|
TemplateHandler.prototype.onTemplate = function ( token, cb ) {
|
2012-01-17 23:18:33 +00:00
|
|
|
//console.log('onTemplate! ' + JSON.stringify( token, null, 2 ) +
|
|
|
|
// ' args: ' + JSON.stringify( this.manager.args ));
|
2012-01-13 18:48:25 +00:00
|
|
|
|
|
|
|
this.parentCB = cb;
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-06 14:30:55 +00:00
|
|
|
// check for 'subst:'
|
|
|
|
// check for variable magic names
|
|
|
|
// check for msg, msgnw, raw magics
|
|
|
|
// check for parser functions
|
|
|
|
|
2012-01-10 01:09:50 +00:00
|
|
|
// create a new temporary frame for argument and title expansions
|
2012-01-11 00:05:51 +00:00
|
|
|
var templateTokenTransformData = {
|
2012-01-06 14:30:55 +00:00
|
|
|
args: {},
|
2012-01-11 19:48:49 +00:00
|
|
|
manager: this.manager,
|
2012-01-13 18:48:25 +00:00
|
|
|
outstanding: 1, // Avoid premature finish
|
2012-01-10 01:09:50 +00:00
|
|
|
cb: cb,
|
2012-01-11 00:05:51 +00:00
|
|
|
origToken: token,
|
|
|
|
isAsync: false
|
2012-01-06 14:30:55 +00:00
|
|
|
},
|
2012-01-10 01:09:50 +00:00
|
|
|
transformCB,
|
2012-01-06 14:30:55 +00:00
|
|
|
i = 0,
|
|
|
|
kvs = [],
|
|
|
|
res,
|
|
|
|
kv;
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-14 00:58:20 +00:00
|
|
|
var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]]
|
2012-01-17 22:29:26 +00:00
|
|
|
.concat( this._nameArgs( token.orderedArgs ) );
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-18 19:38:32 +00:00
|
|
|
//console.log( 'before AttributeTransformManager: ' +
|
|
|
|
// JSON.stringify( attributes, null, 2 ) );
|
2012-01-13 18:48:25 +00:00
|
|
|
new AttributeTransformManager(
|
|
|
|
this.manager,
|
|
|
|
this._returnAttributes.bind( this, templateTokenTransformData )
|
2012-01-11 00:05:51 +00:00
|
|
|
).process( attributes );
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-13 18:48:25 +00:00
|
|
|
// Unblock finish
|
|
|
|
templateTokenTransformData.outstanding--;
|
2012-01-11 19:48:49 +00:00
|
|
|
if ( templateTokenTransformData.outstanding === 0 ) {
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log( 'direct call');
|
2012-01-18 19:38:32 +00:00
|
|
|
// All attributes are fully expanded synchronously (no IO was needed)
|
2012-01-11 00:05:51 +00:00
|
|
|
return this._expandTemplate ( templateTokenTransformData );
|
2012-01-06 14:30:55 +00:00
|
|
|
} else {
|
2012-01-11 00:05:51 +00:00
|
|
|
templateTokenTransformData.isAsync = true;
|
2012-01-06 14:30:55 +00:00
|
|
|
return { async: true };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-01-17 22:29:26 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2012-01-18 19:38:32 +00:00
|
|
|
TemplateHandler.prototype._returnAttributes = function ( templateTokenTransformData,
|
|
|
|
attributes )
|
|
|
|
{
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log( 'TemplateHandler._returnAttributes: ' + JSON.stringify(attributes) );
|
2012-01-11 00:05:51 +00:00
|
|
|
// Remove the target from the attributes
|
|
|
|
templateTokenTransformData.target = attributes[0][1];
|
|
|
|
attributes.shift();
|
|
|
|
templateTokenTransformData.expandedArgs = attributes;
|
|
|
|
if ( templateTokenTransformData.isAsync ) {
|
|
|
|
this._expandTemplate ( templateTokenTransformData );
|
2012-01-10 01:09:50 +00:00
|
|
|
}
|
2012-01-17 22:29:26 +00:00
|
|
|
};
|
2012-01-06 14:30:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch, tokenize and token-transform a template after all arguments and the
|
|
|
|
* target were expanded in frame.
|
|
|
|
*/
|
2012-01-11 00:05:51 +00:00
|
|
|
TemplateHandler.prototype._expandTemplate = function ( templateTokenTransformData ) {
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log('TemplateHandler.expandTemplate: ' +
|
|
|
|
// JSON.stringify( templateTokenTransformData, null, 2 ) );
|
2012-01-10 01:09:50 +00:00
|
|
|
// First, check the target for loops
|
2012-01-14 00:58:20 +00:00
|
|
|
var target = this.manager.env.normalizeTitle(
|
|
|
|
this.manager.env.tokensToString( templateTokenTransformData.target )
|
|
|
|
);
|
|
|
|
if( this.manager.loopCheck.check( target ) ) {
|
|
|
|
// Loop detected, abort!
|
|
|
|
return {
|
|
|
|
tokens: [
|
|
|
|
{
|
|
|
|
type: 'TEXT',
|
2012-01-17 20:01:21 +00:00
|
|
|
value: 'Template loop detected: '
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'TAG',
|
|
|
|
name: 'a',
|
|
|
|
attrib: [['href', target]]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'TEXT',
|
|
|
|
value: target
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'ENDTAG',
|
|
|
|
name: 'a'
|
2012-01-14 00:58:20 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
|
|
|
}
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-09 19:33:49 +00:00
|
|
|
// Create a new nested transformation pipeline for the input type
|
|
|
|
// (includes the tokenizer and synchronous stage-1 transforms for
|
|
|
|
// 'text/wiki' input).
|
|
|
|
// Returned pipe (for now):
|
|
|
|
// { first: tokenizer, last: AsyncTokenTransformManager }
|
2012-01-17 22:29:26 +00:00
|
|
|
//console.log( 'expanded args: ' +
|
2012-01-17 23:18:33 +00:00
|
|
|
// JSON.stringify( this.manager.env.KVtoHash(
|
|
|
|
// templateTokenTransformData.expandedArgs ) ) );
|
2012-01-17 22:29:26 +00:00
|
|
|
|
2012-01-17 23:18:33 +00:00
|
|
|
var inputPipeline = this.manager.newChildPipeline(
|
2012-01-14 00:58:20 +00:00
|
|
|
this.manager.inputType || 'text/wiki',
|
2012-01-17 22:29:26 +00:00
|
|
|
this.manager.env.KVtoHash( templateTokenTransformData.expandedArgs ),
|
2012-01-14 00:58:20 +00:00
|
|
|
templateTokenTransformData.target
|
2012-01-11 19:48:49 +00:00
|
|
|
);
|
2012-01-10 01:09:50 +00:00
|
|
|
|
2012-01-13 18:48:25 +00:00
|
|
|
// Hook up the inputPipeline output events to call back our parentCB.
|
2012-01-17 23:18:33 +00:00
|
|
|
inputPipeline.addListener( 'chunk', this._onChunk.bind ( this ) );
|
|
|
|
inputPipeline.addListener( 'end', this._onEnd.bind ( this ) );
|
2012-01-10 01:09:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Resolve a possibly relative link
|
2012-01-13 18:48:25 +00:00
|
|
|
var templateName = this.manager.env.resolveTitle(
|
2012-01-14 00:58:20 +00:00
|
|
|
target,
|
2012-01-13 18:48:25 +00:00
|
|
|
'Template'
|
|
|
|
);
|
2012-01-18 19:38:32 +00:00
|
|
|
this._fetchTemplateAndTitle( templateName,
|
|
|
|
this._processTemplateAndTitle.bind( this, inputPipeline )
|
|
|
|
);
|
2012-01-09 19:33:49 +00:00
|
|
|
|
2012-01-06 14:30:55 +00:00
|
|
|
// Set up a pipeline:
|
|
|
|
// fetch template source -> tokenizer
|
2012-01-09 17:49:16 +00:00
|
|
|
// getInputPipeline( inputType )
|
|
|
|
// normally tokenizer -> transforms 1/2
|
|
|
|
// encapsulation by default, generic de-encapsulation in phase 3
|
|
|
|
// { type: 'object', name: 'template', value: [tokens] }
|
|
|
|
// -> then un-wrap and replace with contents in phase 3 if for-viewing
|
|
|
|
// mode
|
2012-01-06 14:30:55 +00:00
|
|
|
// -> TokenTransformDispatcher (phase 1/2 only, with frame passed in)
|
|
|
|
// -> frame.cb( tokens )
|
|
|
|
|
|
|
|
|
|
|
|
// XXX: notes from brion's mediawiki.parser.environment
|
|
|
|
// resolve template name
|
|
|
|
// load template w/ canonical name
|
|
|
|
// load template w/ variant names
|
|
|
|
// recursion depth check
|
|
|
|
// fetch from DB or interwiki
|
|
|
|
// infinte loop check
|
2012-01-13 18:48:25 +00:00
|
|
|
|
|
|
|
if ( this.isAsync ) {
|
|
|
|
return {};
|
|
|
|
} else {
|
|
|
|
return this.result;
|
|
|
|
}
|
2012-01-06 14:30:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-01-10 01:09:50 +00:00
|
|
|
/**
|
|
|
|
* Convert AsyncTokenTransformManager output chunks to parent callbacks
|
|
|
|
*/
|
|
|
|
TemplateHandler.prototype._onChunk = function( chunk ) {
|
|
|
|
// We encapsulate the output by default, so collect tokens here.
|
|
|
|
this.resultTokens = this.resultTokens.concat( chunk );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2012-01-17 20:01:21 +00:00
|
|
|
* Handle the end event emitted by the parser pipeline by calling our parentCB
|
|
|
|
* with notYetDone set to false.
|
2012-01-10 01:09:50 +00:00
|
|
|
*/
|
2012-01-17 20:01:21 +00:00
|
|
|
TemplateHandler.prototype._onEnd = function( token ) {
|
2012-01-10 01:09:50 +00:00
|
|
|
// Encapsulate the template in a single token, which contains all the
|
|
|
|
// information needed for the editor.
|
2012-01-14 00:58:20 +00:00
|
|
|
var res = this.resultTokens;
|
2012-01-17 20:01:21 +00:00
|
|
|
// Remove 'end' token from end
|
|
|
|
if ( res.length && res[res.length - 1].type === 'END' ) {
|
|
|
|
res.pop();
|
|
|
|
}
|
|
|
|
|
2012-01-14 00:58:20 +00:00
|
|
|
/*
|
2012-01-13 18:48:25 +00:00
|
|
|
[{
|
|
|
|
type: 'TAG',
|
|
|
|
name: 'div',
|
|
|
|
attribs: [['data-source', 'template']],
|
|
|
|
args: this.manager.args // Here, the editor needs wikitext.
|
|
|
|
}].concat(
|
|
|
|
// XXX: Mark source in attribute on result tokens, so that
|
|
|
|
// the visual editor can detect structures from templates!
|
|
|
|
this.resultTokens,
|
|
|
|
[{ type: 'ENDTAG', name: 'div' }]
|
|
|
|
);
|
2012-01-14 00:58:20 +00:00
|
|
|
*/
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log( 'TemplateHandler._onEnd: ' + JSON.stringify( res, null, 2 ) );
|
|
|
|
|
|
|
|
if ( this.isAsync ) {
|
|
|
|
this.parentCB( res, false );
|
|
|
|
} else {
|
|
|
|
this.result = { tokens: res };
|
|
|
|
this.reset();
|
|
|
|
}
|
2012-01-10 01:09:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process a fetched template source
|
|
|
|
*/
|
2012-01-17 23:18:33 +00:00
|
|
|
TemplateHandler.prototype._processTemplateAndTitle = function( pipeline, src, title ) {
|
2012-01-10 01:09:50 +00:00
|
|
|
// Feed the pipeline. XXX: Support different formats.
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log( 'TemplateHandler._processTemplateAndTitle: ' + src );
|
2012-01-17 23:18:33 +00:00
|
|
|
pipeline.process ( src );
|
2012-01-10 01:09:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-01-06 17:19:14 +00:00
|
|
|
/**
|
|
|
|
* Fetch a template
|
|
|
|
*/
|
2012-01-10 01:09:50 +00:00
|
|
|
TemplateHandler.prototype._fetchTemplateAndTitle = function( title, callback ) {
|
2012-01-06 17:19:14 +00:00
|
|
|
// @fixme normalize name?
|
2012-01-18 19:38:32 +00:00
|
|
|
var self = this;
|
2012-01-13 18:48:25 +00:00
|
|
|
if (title in this.manager.env.pageCache) {
|
2012-01-06 17:19:14 +00:00
|
|
|
// @fixme should this be forced to run on next event?
|
2012-01-14 00:58:20 +00:00
|
|
|
callback( this.manager.env.pageCache[title], title );
|
2012-01-18 19:38:32 +00:00
|
|
|
} else if ( ! this.manager.env.fetchTemplates ) {
|
|
|
|
callback('Page/template fetching disabled, and no cache for ' + title);
|
2012-01-06 17:19:14 +00:00
|
|
|
} else {
|
|
|
|
// whee fun hack!
|
2012-01-18 19:38:32 +00:00
|
|
|
|
|
|
|
this.isAsync = true;
|
|
|
|
console.log( 'trying to fetch ' + title );
|
2012-01-13 18:48:25 +00:00
|
|
|
//console.log(this.manager.env.pageCache);
|
2012-01-18 19:38:32 +00:00
|
|
|
var url = this.manager.env.wgScriptPath + '/api' +
|
|
|
|
this.manager.env.wgScriptExtension +
|
|
|
|
'?format=json&action=query&prop=revisions&rvprop=content&titles=' + title;
|
|
|
|
|
|
|
|
request({
|
|
|
|
method: 'GET',
|
|
|
|
//followRedirect: false,
|
|
|
|
url: url,
|
|
|
|
headers: {
|
|
|
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1 Iceweasel/9.0.1'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function (error, response, body) {
|
|
|
|
console.log( 'response for ' + title + ': ' + body );
|
|
|
|
if(error) {
|
|
|
|
console.log(error);
|
|
|
|
callback('Page/template fetch failure for title ' + title);
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(response.statusCode == 200) {
|
|
|
|
try{
|
|
|
|
console.log( 'body: ' + body );
|
|
|
|
data = JSON.parse(body);
|
|
|
|
var src = null;
|
|
|
|
$.each(data.query.pages, function(i, page) {
|
|
|
|
if (page.revisions && page.revisions.length) {
|
|
|
|
src = page.revisions[0]['*'];
|
|
|
|
title = page.title;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
console.log( 'Page ' + title + ': got ' + src );
|
|
|
|
self.manager.env.pageCache[title] = src;
|
|
|
|
callback(src, title);
|
|
|
|
} catch(e) {
|
|
|
|
console.log("Error: while parsing result. Error was: ");
|
|
|
|
console.log(e);
|
|
|
|
console.log("Response that didn't parse was:\n" + body);
|
|
|
|
|
|
|
|
data = {
|
|
|
|
error: '',
|
|
|
|
errorWfMsg: 'chat-err-communicating-with-mediawiki',
|
|
|
|
errorMsgParams: []
|
|
|
|
};
|
|
|
|
}
|
|
|
|
console.log(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: The jQuery version does not quite work with node, but we keep
|
|
|
|
* it around for now.
|
2012-01-06 17:19:14 +00:00
|
|
|
$.ajax({
|
2012-01-18 19:38:32 +00:00
|
|
|
url: url,
|
2012-01-06 17:19:14 +00:00
|
|
|
data: {
|
|
|
|
format: 'json',
|
2012-01-18 19:38:32 +00:00
|
|
|
action: 'query',
|
|
|
|
prop: 'revisions',
|
|
|
|
rvprop: 'content',
|
|
|
|
titles: title
|
2012-01-06 17:19:14 +00:00
|
|
|
},
|
2012-01-18 19:38:32 +00:00
|
|
|
success: function(data, statusString, xhr) {
|
|
|
|
console.log( 'Page ' + title + ' success ' + JSON.stringify( data ) );
|
2012-01-06 17:19:14 +00:00
|
|
|
var src = null, title = null;
|
|
|
|
$.each(data.query.pages, function(i, page) {
|
|
|
|
if (page.revisions && page.revisions.length) {
|
|
|
|
src = page.revisions[0]['*'];
|
|
|
|
title = page.title;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (typeof src !== 'string') {
|
2012-01-18 19:38:32 +00:00
|
|
|
console.log( 'Page ' + title + 'not found! Got ' + src );
|
2012-01-13 18:48:25 +00:00
|
|
|
callback( 'Page ' + title + ' not found' );
|
2012-01-06 17:19:14 +00:00
|
|
|
} else {
|
2012-01-18 19:38:32 +00:00
|
|
|
// Add to cache
|
|
|
|
console.log( 'Page ' + title + ': got ' + src );
|
|
|
|
this.manager.env.pageCache[title] = src;
|
2012-01-06 17:19:14 +00:00
|
|
|
callback(src, title);
|
|
|
|
}
|
|
|
|
},
|
2012-01-18 19:38:32 +00:00
|
|
|
error: function(xhr, msg, err) {
|
|
|
|
console.log( 'Page/template fetch failure for title ' +
|
|
|
|
title + ', url=' + url + JSON.stringify(xhr) + ', err=' + err );
|
2012-01-13 18:48:25 +00:00
|
|
|
callback('Page/template fetch failure for title ' + title);
|
2012-01-06 17:19:14 +00:00
|
|
|
},
|
|
|
|
dataType: 'json',
|
2012-01-18 19:38:32 +00:00
|
|
|
cache: false, // @fixme caching, versions etc?
|
|
|
|
crossDomain: true
|
|
|
|
});
|
|
|
|
*/
|
2012-01-06 17:19:14 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-01-09 17:49:16 +00:00
|
|
|
/**
|
|
|
|
* Expand template arguments with tokens from the containing frame.
|
|
|
|
*/
|
2012-01-06 14:30:55 +00:00
|
|
|
TemplateHandler.prototype.onTemplateArg = function ( token, cb, frame ) {
|
2012-01-17 22:29:26 +00:00
|
|
|
|
|
|
|
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 ));
|
2012-01-17 23:18:33 +00:00
|
|
|
var argName = this.manager.env.tokensToString( attributes[0][0] ).trim(),
|
2012-01-17 22:29:26 +00:00
|
|
|
defaultValue = attributes[0][1],
|
|
|
|
res;
|
2012-01-17 23:18:33 +00:00
|
|
|
if ( argName in this.manager.args ) {
|
2012-01-06 14:30:55 +00:00
|
|
|
// return tokens for argument
|
2012-01-17 22:29:26 +00:00
|
|
|
//console.log( 'templateArg found: ' + argName +
|
2012-01-17 23:18:33 +00:00
|
|
|
// ' vs. ' + JSON.stringify( this.manager.args ) );
|
|
|
|
res = this.manager.args[argName];
|
2012-01-06 14:30:55 +00:00
|
|
|
} else {
|
2012-01-17 22:29:26 +00:00
|
|
|
//console.log( 'templateArg not found: ' + argName +
|
2012-01-17 23:18:33 +00:00
|
|
|
// ' vs. ' + JSON.stringify( this.manager.args ) );
|
2012-01-06 17:19:14 +00:00
|
|
|
if ( token.attribs.length > 1 ) {
|
2012-01-17 22:29:26 +00:00
|
|
|
res = defaultValue;
|
2012-01-06 17:19:14 +00:00
|
|
|
} else {
|
2012-01-17 22:29:26 +00:00
|
|
|
res = [{ type: 'TEXT', value: '{{{' + argName + '}}}' }];
|
2012-01-06 17:19:14 +00:00
|
|
|
}
|
2012-01-06 14:30:55 +00:00
|
|
|
}
|
2012-01-17 22:29:26 +00:00
|
|
|
if ( token.resultTokens !== false ) {
|
|
|
|
cb( res );
|
|
|
|
} else {
|
|
|
|
token.resultTokens = res;
|
|
|
|
}
|
2012-01-06 14:30:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (typeof module == "object") {
|
|
|
|
module.exports.TemplateHandler = TemplateHandler;
|
|
|
|
}
|