Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 70 additions & 9 deletions hbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,84 @@

import Handlebars from 'handlebars';

/**
* Attaches the precompiled Handlebars template in a CommonJs module,
* and attaches any depended partials on `load` for system.js to
* fetch. Also registers the partials as such on the Handlebars
* runtime.
*/
export function translate(load) {
let precompiled = Handlebars.precompile(load.source);
let handlebarsRuntimePath = System.normalizeSync('handlebars/handlebars.runtime.js', __moduleName);

// in builds we want to embed the canonical name for the handlebars runtime
if (System.getCanonicalName) {
handlebarsRuntimePath = System.getCanonicalName(handlebarsRuntimePath);
}
let ast = Handlebars.parse(load.source);
let partials = findPartials(ast);
load.metadata.deps = partials;

let precompiled = Handlebars.precompile(load.source);
let handlebarsRuntimePath = System.normalizeSync('handlebars/handlebars.runtime', __moduleName);

let output;
if (load.metadata.format === 'esm') {
output = `import {Handlebars} from '${handlebarsRuntimePath}'; \n export default Handlebars.template(${precompiled});`;
let partialReqs = partials.map((dep, i) => {
return `import tmpl$i from '${dep}';`;
}).join('\n');
let registry = partials.map((dep, i) => {
return `Handlebars.registerPartial('${dep}', tmpl${i});`;
}).join('\n');

output = `
import {Handlebars} from '${handlebarsRuntimePath}';
${partialReqs}
${registry}
export default Handlebars.template(${precompiled});
`;
} else if (load.metadata.format === 'amd') {
output = `define(['${handlebarsRuntimePath}'], function (Handlebars) { return Handlebars.template(${precompiled}); });`;
let partialReqs = partials.map(dep => `'${dep}'`).join(', ');
let args = partials.map((dep, i) => `tmpl${i}`).join(', ');
let registry = partials.map((dep, i) => {
return `Handlebars.registerPartial('${dep}', tmpl${i});`;
}).join('\n ');

output = `
define(['${handlebarsRuntimePath}', ${partialReqs}],
function(Handlebars, ${args}) {
${registry};
return Handlebars.template(${precompiled});
});
`;
} else {
output = `var Handlebars = require('${handlebarsRuntimePath}'); \n module.exports = Handlebars.template(${precompiled});`;
let partialReqs = partials.map(dep => {
return `Handlebars.registerPartial('${dep}', require('${dep}'));`;
}).join('\n');
output = `
var Handlebars = require('${handlebarsRuntimePath}');
${partialReqs};
module.exports = Handlebars.template(${precompiled});
`;
}
load.source = output;
return output;
}

/**
* Recursively trawls a Handlebars AST, providing the string names of
* all invoked partials.
*/
function findPartials(astRoot) {
let partials = [];

let recurse = function(ast) {
if (!ast) {
return;
} else if (Array.isArray(ast)) {
ast.forEach(n => recurse(n));
} else if (ast.type === 'PartialStatement') {
partials.push(ast.name.original);
} else if (typeof ast === 'object') {
let subnodes = Object.keys(ast).map(k => ast[k]);
subnodes.forEach(n => recurse(n));
}
};
recurse(astRoot);

return partials;
}