Skip to content

Instantly share code, notes, and snippets.

@adamblank
Last active December 27, 2015 12:48
Show Gist options
  • Save adamblank/7328089 to your computer and use it in GitHub Desktop.
Save adamblank/7328089 to your computer and use it in GitHub Desktop.
_.reverseTemplate() attempts to reverse engineer the original object used to generate a rendered underscore.js template output by comparing the output string to the template string.
/* Extend the underscore global object with the following method:
*
* https://gist.github.com/adamblank/7328089
*
* reverseTemplate attempts to reverse engineer the original object used to generate
* the rendered output by comparing the output string to the underscore template string.
*
* Paramaters
* - renderedOutput - the string that was generated from the template
* - template - the template string used to generate the compiled underscore template (not the compiled template function.)
*
* Dependencies
* - underscore.js
*
* Limitations
* - This method can only reverse engineer templates that only use interpolation
* - Values used in template must be top-level properties only (i.e. { prop: 'value' } NOT { obj: { prop: 'value }} )
* - Interpolation values cannot be right next to each other (e.g. <%= name %><%= age %>)
*/
_.reverseTemplate = function(renderedOutput, template) {
function extractValue(renderedOutput, template, resultObj) {
//get underscore's template interpolation regular expression (remove global flag)
var regex = _.templateSettings.interpolate instanceof RegExp ? new RegExp(_.templateSettings.interpolate.source) : _.templateSettings.interpolate,
match = template.match(regex),
prop,
templateSplit,
secondSplitPivot,
value;
if (!match) {
return resultObj;
}
//get the specifc template interpolation property
prop = match[1].replace(/ /g,'');
templateSplit = template.split(match[0]);
//grab subsection between this interpolation placeholder and the next (if any)
secondSplitPivot = templateSplit[1].split(regex)[0];
//slice off everything before interpolation value
value = renderedOutput.replace(templateSplit[0], '');
//if theres more after the value, slice it off also
if (secondSplitPivot) {
value = value.split(secondSplitPivot)[0];
}
resultObj[prop] = value;
return extractValue(renderedOutput, template.replace(regex, value), resultObj);
}
return extractValue(renderedOutput, template, {});
}
/*
* Test
*/
//change underscore's templating interpolation delimiter to something nicer (not required)
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
_.reverseTemplate('this is a test to make sure extractTemplateValues works', 'this is a {{ activity }} to make sure {{ plugin }} {{ status }}');
//outputs: Object {activity: "test", plugin: "extractTemplateValues", status: "works"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment