Skip to content

Instantly share code, notes, and snippets.

@nknapp
Created March 11, 2017 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nknapp/ff5b93c7366f6458cea10c88c9521069 to your computer and use it in GitHub Desktop.
Save nknapp/ff5b93c7366f6458cea10c88c9521069 to your computer and use it in GitHub Desktop.
Concept for source-mapping the output of a Handlebars-template back to the template
var Handlebars = require('handlebars');
var LineCounter = require("line-counter");
var env = Handlebars.create();
function SourceMapCompiler() {
}
SourceMapCompiler.prototype = new Handlebars.JavaScriptCompiler();
SourceMapCompiler.prototype.appendToBuffer = function (source, location, explicit) {
var result = Handlebars.JavaScriptCompiler.prototype.appendToBuffer.apply(this, [source, location, true])
return [`helpers.$consumeSourceMapEntry(${result[1].line}, ${result[1].column}, buffer.length);`, result]
}
env.JavaScriptCompiler = SourceMapCompiler
var sourceMappings = []
// A helper seems to be about the only way to pass data from the template function to the calling context
env.registerHelper("$consumeSourceMapEntry", function (sourceLine, sourceColumn, targetIndex) {
sourceMappings.push({
source: {
column: sourceColumn+1,
line: sourceLine
},
target: targetIndex
})
}
)
const template = '1{{abc}}\n2a\n3{{cde}}\n4\n5b\n6\n\n\n\n\n{{abc}}';
var output = env.compile(template)({
abc: 'a\nmultiline\string',
cde: 'x'
});
// Map target-indexes to lines/columns
var counter = new LineCounter(output);
sourceMappings.forEach(function(entry) {
entry.target = counter.locate(entry.target)
})
console.log(sourceMappings)
console.log(JSON.stringify({template, output},null,2))
@nknapp
Copy link
Author

nknapp commented Mar 11, 2017

This is a proof-of-concept. The source-maps that the Handlebars project generates are just from compiled-template to the template (as far as I know). For debugging and developing templates, what I sometimes need is from "template-output" to "template".
This is an idea of how to achieve it, without changing Handlebars itself.

As a workaround, the mappings are passed back to the callee through a helper. This should actually be a hook inside Handlebars, but I have to think about it.

@nknapp
Copy link
Author

nknapp commented Mar 11, 2017

Mhm, this does not work with partials and block-helpers:

  • The buffer is new when sub-programs are executed. Somehow I have to grab the point where the partial is called and recalculated the target-index based on that point.
  • The SourceNodes in the compile function do not have the information in which partial they occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment