multivocal
Version:
A node.js library to assist with building best practice, configuration driven, Actions for the Google Assistant.
205 lines (173 loc) • 4.79 kB
JavaScript
var Handlebars = require('handlebars');
var helpers = require('handlebars-helpers')({
handlebars: Handlebars
});
exports.Handlebars = Handlebars;
var config = {
allowProtoPropertiesByDefault: true
};
exports.config = config;
exports.setConfig = function( newConfig ){
config = newConfig;
return config;
}
// Load our own Handlebars functions
var funcs = require('./template-functions');
var fkeys = Object.keys( funcs );
fkeys.map( fname => {
var func = funcs[fname];
Handlebars.registerHelper( fname, func );
});
var methods = {};
exports.execute = function( templateStr, env ){
var template = Handlebars.compile( templateStr );
env['_This'] = undefined;
var ret = template( env, config );
if( env['_This'] ){
ret = env['_This'];
}
return ret;
};
exports.eval = function( template, env, method ){
if( typeof method === 'string' ){
method = methods[method];
}
if( !method ){
if( typeof template === 'boolean' || typeof template === 'number' ){
return template;
} else if( typeof template === 'object' && !Array.isArray(template) ){
method = exports.evalObj;
} else if( Array.isArray(template) ){
method = exports.evalArray;
} else {
method = exports.evalConcatStr;
}
}
var oldTemplateResult = env['_Result'];
env['_Result'] = undefined;
var ret = method( template, env );
env['_Result'] = oldTemplateResult;
return ret;
};
methods.Typed = exports.eval;
// Don't actually evaluate it. Included for completeness
exports.evalIdentity = function( obj ){
return obj;
};
methods.Identity = exports.evalIdentity;
exports.evalConcatStr = function( template, env ){
if( Array.isArray(template) ){
template = template.join('');
}
if( typeof template === 'number' ){
return template;
}
return exports.execute( template, env );
};
methods.Str = exports.evalConcatStr;
exports.evalBoolean = function( template, env ){
var ret;
if( Array.isArray( template ) ){
template = {
Terms: template,
Op: 'and'
};
}
if( typeof template === 'string' ){
template = {
Terms: [template],
Op: 'and'
};
}
if( !template.Terms ){
console.error('evalBoolean bad format', template);
} else if( template.Terms.length === 1 ){
ret = exports.execute( template.Terms[0], env );
if( !ret || ret === 'false' ){
ret = false;
}
} else {
var left = {
Terms: [template.Terms[0]],
Op: template.Op
};
var right = {
Terms: template.Terms.slice(1),
Op: template.Op
};
ret = exports.evalBoolean( left, env );
if( template.Op === 'or' ){
ret = ret || exports.evalBoolean( right, env );
} else {
ret = ret && exports.evalBoolean( right, env );
}
}
//console.log('Template evalBoolean', template, ret);
return ret;
};
methods.Bool = exports.evalBoolean;
/**
* Evaluate each item in an array as a template
* @param templates
* @param env
* @returns {Array}
*/
exports.evalArray = function( templates, env ){
if( !Array.isArray( templates ) ){
templates = [templates];
}
var ret = templates.map( template => exports.eval( template, env ) );
return ret;
};
methods.Array = exports.evalArray;
exports.evalObj = function( templateObj, env ){
if( typeof templateObj === 'string' ){
templateObj = JSON.parse( templateObj );
} else if( Array.isArray( templateObj ) ){
return exports.evalArray( templateObj, env );
} else if( templateObj && templateObj.CriteriaMatch ){
return exports.evalObjCriteria( templateObj, env );
}
var ret = {};
if( typeof env['_Result'] == 'undefined' ){
env['_Result'] = ret;
}
var keys = Object.keys( templateObj );
keys.map( key => {
var valTemplate = templateObj[key];
var val;
if( typeof valTemplate === 'string' ){
val = exports.evalConcatStr( valTemplate, env );
} else if( Array.isArray( valTemplate ) ){
val = exports.evalArray( valTemplate, env );
} else if( typeof valTemplate === 'object' ){
val = exports.evalObj( valTemplate, env );
} else {
val = valTemplate;
}
ret[key] = val;
});
return ret;
};
exports.evalObjCriteria = function( criteriaObj, env ){
var ret;
if( !criteriaObj || !criteriaObj.CriteriaMatch ){
return "";
}
var criteriaMatchList = criteriaObj.CriteriaMatch;
for( var co=0; co<criteriaMatchList.length && !ret; co++ ){
var criteriaMatch = criteriaMatchList[co];
if( criteriaMatch ){
var criteria = criteriaMatch.Criteria;
var eval = exports.evalBoolean( criteria, env );
if( eval ){
ret = exports.eval( criteriaMatch.Value, env );
}
}
}
if( !ret ){
ret = criteriaObj.Default;
}
return ret;
}
exports.Methods = methods;